<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[khalilstemmler.com RSS Feed]]></title><description><![CDATA[Advanced TypeScript & Node.js guides for large-scale applications. Learn to write flexible, maintainable TypeScript.]]></description><link>https://khalilstemmler.com</link><generator>GatsbyJS</generator><lastBuildDate>Wed, 13 May 2026 12:51:16 GMT</lastBuildDate><item><title><![CDATA[The Power of Composition]]></title><description><![CDATA[Quick question. How often do you see this type of code? composition conditional problem If the answer is "a lot", that's okay - we've all…]]></description><link>https://khalilstemmler.com/articles/composition-oop/the-power-of-composition/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/composition-oop/the-power-of-composition/</guid><pubDate>Tue, 25 Nov 2025 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Quick question.&lt;/p&gt;
&lt;p&gt;How often do you see this type of code?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/composition/conditional-problem.png&quot; alt=&quot;composition conditional problem&quot;&gt;&lt;/p&gt;
&lt;p&gt;If the answer is &quot;a lot&quot;, that&apos;s okay - we&apos;ve all been there.&lt;/p&gt;
&lt;p&gt;Especially in the Code-First Phase of Craftship. &lt;/p&gt;
&lt;p&gt;(&lt;a href=&quot;https://www.essentialist.dev/offers/MDjktWcQ&quot;&gt;Learn more about the 5 Phases in this free guide here&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;However, if you&apos;re seeing this a lot, it&apos;s a good sign that you may be missing Composition, which is one of 12 Essentials that -- when balanced properly, tends to lead to testable, flexible, maintainable code...&lt;/p&gt;
&lt;p&gt;... and when out of balance, tends to lead to significant issues that are REALLY hard to fix later on down the road.&lt;/p&gt;
&lt;p&gt;In my estimation, nearly every problem you face in your codebase can be traced back down to at least one of the 12 Essentials.&lt;/p&gt;
&lt;p&gt;This took me a long time to figure out, so I&apos;ll do my best to explain in a short email.&lt;/p&gt;
&lt;h2 id=&quot;What-is-composition&quot; style=&quot;position:relative;&quot;&gt;What is composition?&lt;a href=&quot;#What-is-composition&quot; aria-label=&quot;What is composition permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Composition is simply:&lt;/p&gt;
&lt;p&gt;How your application “comes together.”
How objects get created.
How dependencies get wired.
How environments boot.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/composition/composition-essential.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;You use composition every time you boot your app:&lt;/p&gt;
&lt;p&gt;Boot in dev mode → you need composition&lt;/p&gt;
&lt;p&gt;Boot in test mode → you need composition&lt;/p&gt;
&lt;p&gt;Boot integration tests → you need composition&lt;/p&gt;
&lt;p&gt;Boot in production → you need composition&lt;/p&gt;
&lt;p&gt;Boot a CLI tool? → you need composition&lt;/p&gt;
&lt;p&gt;Boot a worker? → you need composition&lt;/p&gt;
&lt;p&gt;Composition is the grand configurer-er.
The mechanism everything else sits on.&lt;/p&gt;
&lt;p&gt;You know those little Russian Dolls? (they&apos;re called Matryoshka dolls).&lt;/p&gt;
&lt;p&gt;Well, that&apos;s kinda how I see composition. Your application is composed from parts and wholes, coming together to fulfill a larger responsibility.&lt;/p&gt;
&lt;p&gt;One environment wrapping the next, cleanly composed, cleanly booted.&lt;/p&gt;
&lt;p&gt;It&apos;s quite beautiful, really.&lt;/p&gt;
&lt;p&gt;And if structured correctly, you can design your application to spin up the right way, with the right parts, for the right context, in a simple way, from a single location (typically called the Composition Root).&lt;/p&gt;
&lt;p&gt;This is immensely powerful, and also immensely debilitating if you don&apos;t have a composition root.&lt;/p&gt;
&lt;h2 id=&quot;What-most-devs-do&quot; style=&quot;position:relative;&quot;&gt;What most devs do&lt;a href=&quot;#What-most-devs-do&quot; aria-label=&quot;What most devs do permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most developers at the Code-First phase aren&apos;t yet aware of how important this essential is downstream, so they miss it.&lt;/p&gt;
&lt;p&gt;Instead, you&apos;ll end up seeing things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;imports scattered all over the place&lt;/li&gt;
&lt;li&gt;mutating global state&lt;/li&gt;
&lt;li&gt;using environment variable checks &lt;/li&gt;
&lt;li&gt;hacking dependencies in place&lt;/li&gt;
&lt;li&gt;coupling everything in a single controller or Express.js route&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And yeah — it works…&lt;/p&gt;
&lt;p&gt;until the moment you try to test it.&lt;/p&gt;
&lt;p&gt;Or deploy it.&lt;/p&gt;
&lt;p&gt;Or run it in a different environment.&lt;/p&gt;
&lt;p&gt;Or swap a dependency.&lt;/p&gt;
&lt;p&gt;Or add a new feature.&lt;/p&gt;
&lt;p&gt;Then it turns into pain.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Ask me how I know&lt;/em&gt; 😅&lt;/p&gt;
&lt;p&gt;This is one of the root causes behind fragile systems.&lt;/p&gt;
&lt;p&gt;It&apos;s also at the root of why you can&apos;t write tests.&lt;/p&gt;
&lt;p&gt;I honestly think that&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Developers who say they “hate testing” don’t actually hate testing. They hate the mess they have to fight through just to test anything. But it comes from a lack of Composition and Horizontal Decoupling (another essential).&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;The-benefits-of-composition&quot; style=&quot;position:relative;&quot;&gt;The benefits of composition&lt;a href=&quot;#The-benefits-of-composition&quot; aria-label=&quot;The benefits of composition permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Clean composition gives you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;real testability&lt;/li&gt;
&lt;li&gt;clean dependency inversion&lt;/li&gt;
&lt;li&gt;multiple composable boot modes (dev, prod, ci, xyz)&lt;/li&gt;
&lt;li&gt;more confidence when refactoring&lt;/li&gt;
&lt;li&gt;the heart of a stable architecture&lt;/li&gt;
&lt;li&gt;the ability to scale your codebase in a modular way (just add new modules)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, one of my favourite things is the ability to just boot my application the exact same way every time, simply specifying the context, and allowing the application to wire itself up properly behind the scenes.&lt;/p&gt;
&lt;p&gt;Like this.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/composition/using-composition-root.png&quot; alt=&quot;Composition Topics Web&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;How-to-fix-it&quot; style=&quot;position:relative;&quot;&gt;How to fix it&lt;a href=&quot;#How-to-fix-it&quot; aria-label=&quot;How to fix it permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It takes a few course modules to fully explain how to fix this without breaking everything, but in summary, the answer is to actually start using Abstraction properly. &lt;/p&gt;
&lt;p&gt;A good place to start? &lt;/p&gt;
&lt;p&gt;Start encapsulating stuff. &lt;/p&gt;
&lt;p&gt;This is a big topic to explain, and there are a lot of smaller topics underneath it (see the below diagram)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/composition/composition-topics-web.png&quot; alt=&quot;Composition Topics Web&quot;&gt;&lt;/p&gt;
&lt;p&gt;But you can begin to untangle this problem by implementing a Layered Architecture, slowly, and being more intentional about the entry points to your various execution environments.&lt;/p&gt;
&lt;p&gt;My recommendation is to implement a single bootstrap location, like a &quot;poor man&apos;s version of composition&quot;.&lt;/p&gt;
&lt;p&gt;You&apos;ll notice that we lean heavily on Dependency Inversion / Injection for this. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/composition/composing-application.png&quot; alt=&quot;Composition Topics Web&quot;&gt;&lt;/p&gt;
&lt;p&gt;From here, we can begin to branch into more sophisticated forms of Composition.&lt;/p&gt;
&lt;p&gt;But in my opinion, if you&apos;re at the Code-First level, this is a great start, in order to start to create some semblance of structure.&lt;/p&gt;
&lt;h2 id=&quot;FAQ&quot; style=&quot;position:relative;&quot;&gt;FAQ&lt;a href=&quot;#FAQ&quot; aria-label=&quot;FAQ permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;What-if-Im-not-doing-composition&quot; style=&quot;position:relative;&quot;&gt;“What if I’m not doing composition?”&lt;a href=&quot;#What-if-Im-not-doing-composition&quot; aria-label=&quot;What if Im not doing composition permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You are.
Everyone is to some degree.
You can’t not compose your app.&lt;/p&gt;
&lt;p&gt;The real question is:&lt;/p&gt;
&lt;p&gt;Are you doing it intentionally or accidentally?&lt;/p&gt;
&lt;p&gt;To what degree of consciousness are you composing your application?&lt;/p&gt;
&lt;h3 id=&quot;How-important-is-this&quot; style=&quot;position:relative;&quot;&gt;“How important is this?”&lt;a href=&quot;#How-important-is-this&quot; aria-label=&quot;How important is this permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It’s one of the 12 Essentials.
Miss it and everything downstream gets harder. Just like all of the other ones.&lt;/p&gt;
&lt;h3 id=&quot;What-are-the-levels&quot; style=&quot;position:relative;&quot;&gt;“What are the levels?”&lt;a href=&quot;#What-are-the-levels&quot; aria-label=&quot;What are the levels permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;All Essentials have a scale of mastery from 1 to 10.&lt;/p&gt;
&lt;p&gt;Sometimes the problem calls for a simpler solution, sometimes a more robust one. Discernment and wisdom to know the difference comes from awareness and practice.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Level 1:&lt;/strong&gt;
Everything in one file (Express controller, Next.js route, etc).
It works — but costs you flexibility.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Level 10:&lt;/strong&gt;
Full-blown DI container, composable boot modes, multi-env testing layers, modules, compositional roots within modules, extremely modular.&lt;/p&gt;
&lt;h2 id=&quot;Final-notes&quot; style=&quot;position:relative;&quot;&gt;Final notes&lt;a href=&quot;#Final-notes&quot; aria-label=&quot;Final notes permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A student in the community built a great DI container. He&apos;s been using it in production with his team for over a year without any issues. Check it out 👉 &lt;a href=&quot;https://github.com/webiny/di&quot;&gt;https://github.com/webiny/di&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Take a look at this solution that one of my mentorship students put together demonstrating how to use composition to compose your backend for testing and running production. &lt;a href=&quot;https://github.com/trikitirem/ddd-forum-be&quot;&gt;https://github.com/trikitirem/ddd-forum-be&lt;/a&gt;. I especially like how he uses abstraction to abstract the composition root based on the context we run the application. Really, really nice implementation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks for reading,&lt;/p&gt;
&lt;p&gt;Khalil&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;As a reminder,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can get &lt;a href=&quot;https://www.essentialist.dev/the-software-essentialist-black-friday-2025&quot;&gt;The Software Essentialist @ 30% off&lt;/a&gt; right now&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.essentialist.dev/offers/bU72esPL/checkout?coupon_code=BLACK-FRIDAY-TESTING&quot;&gt;Testing Mastery is 50% off until December 1st&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;And if you want direct help, I’ve got one more slot open for my 6-month mentorship container.  👉 &lt;a href=&quot;https://tally.so/r/mDqK55&quot;&gt;Apply here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Temporal Decoupling: Why We Use Events & Messages]]></title><description><![CDATA[A few big projects happening right now in essentialist.dev-land. November's theme has been finishing solidbook (finally), pattern-first in…]]></description><link>https://khalilstemmler.com/articles/temporal-decoupling-messaging/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/temporal-decoupling-messaging/</guid><pubDate>Thu, 14 Nov 2024 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;A few big projects happening right now in essentialist.dev-land.&lt;/p&gt;
&lt;p&gt;November&apos;s theme has been finishing solidbook (finally), pattern-first in The Software Essentialist, and... moving!&lt;/p&gt;
&lt;p&gt;Going through and tidying up my bookshelf, I dusted off this one. Have you read it?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/enterprise-integration-patterns.jpg&quot; alt=&quot;Enterprise integration patterns&quot;&gt;&lt;/p&gt;
&lt;p&gt;Written by Gregor Hohpe and Bobby Woolf, it&apos;s a book that explains how messaging systems work, how to connect applications together, the types of problems you&apos;ll encounter, and the vast array patterns that help with solving &apos;em.&lt;/p&gt;
&lt;p&gt;And seriously, there are lot of patterns.&lt;/p&gt;
&lt;p&gt;To be completely honest, when I tried reading it about 6 or so years ago, it didn&apos;t really make much sense to me. &lt;/p&gt;
&lt;p&gt;At that time, yes, I found this topic of messaging fascinating, especially because I was just learning how to use Domain-Driven Design and the Clean Architecture to split my application into logical subdomains (which was a big step for me at the time)..&lt;/p&gt;
&lt;p&gt;But straight up - I was:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1) not at the level of awareness to appreciate the contents, and&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2) not dealing with problems that needed me to use messaging yet&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Even through I tried to read this book back then, the topic was just way too far out and away from my reality.&lt;/p&gt;
&lt;p&gt;At that time, my world involved working in a frontend consultancy building frontend applications, still in that phase struggling to write useful tests (which you can move past pretty quickly in &lt;a href=&quot;https://www.essentialist.dev/testing-mastery&quot;&gt;Testing Mastery&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Nonetheless, the seed was planted in my mind.&lt;/p&gt;
&lt;p&gt;It would take me a number of years to run into higher quality problems, focusing more on backend, fullstack, and then architecture to realize the real burning necessity of messaging.&lt;/p&gt;
&lt;h2 id=&quot;Temporal-Decoupling&quot; style=&quot;position:relative;&quot;&gt;Temporal Decoupling&lt;a href=&quot;#Temporal-Decoupling&quot; aria-label=&quot;Temporal Decoupling permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://www.essentialist.dev/the-software-essentialist&quot;&gt;The Software Essentialist&lt;/a&gt;, one of the 12 Essentials I teach is called Temporal Decoupling.&lt;/p&gt;
&lt;p&gt;The idea is this: every feature you add, change, remove, test - they all happen after or before a policy, command, or something else happens.&lt;/p&gt;
&lt;p&gt;Because your job is entirely about solving problems...&lt;/p&gt;
&lt;p&gt;And the solution to problems can be described as either steps or past tense events ... &lt;/p&gt;
&lt;p&gt;And because reality is cyclical in nature...&lt;/p&gt;
&lt;p&gt;It&apos;s clear that it only makes sense to design in most cases to assume an architecture with the capacity to decouple features from each other using events.&lt;/p&gt;
&lt;p&gt;It&apos;s exactly why Redux, mobx, and any 1-directional data flow system you&apos;ve built on the frontend can scale so well..&lt;/p&gt;
&lt;p&gt;And it&apos;s why CRUD often falls short in the long run, as I learned many years ago..&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/temporal-decoupling-12-essentials.png&quot; alt=&quot;Temporal Decoupling&quot;&gt;
&lt;/p&gt;
&lt;h3 id=&quot;Why-am-I-telling-you-all-of-this&quot; style=&quot;position:relative;&quot;&gt;Why am I telling you all of this?&lt;a href=&quot;#Why-am-I-telling-you-all-of-this&quot; aria-label=&quot;Why am I telling you all of this permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You want to feel confident in your skills as a developer, but maybe you&apos;re worried you&apos;re not focused on the right things.&lt;/p&gt;
&lt;p&gt;Here&apos;s my best take.&lt;/p&gt;
&lt;p&gt;I&apos;ve said this before, and I will say it a million times...&lt;/p&gt;
&lt;p&gt;Your job is not to write code, it is to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;help customers make money &amp;#x26; save money&lt;/li&gt;
&lt;li&gt;help users get back time &amp;#x26; have their time enriched&lt;/li&gt;
&lt;li&gt;write code in such a way that it makes it easy for you and the other developers on your team do the previous two things.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Focus on that and you&apos;ll automatically, as a result, end up mastering what matters.&lt;/p&gt;
&lt;p&gt;What you&apos;ll notice as you continually take on challenges that drive you to learn new things, is that your perspective will continue to expand and rise.&lt;/p&gt;
&lt;p&gt;You&apos;ll be able to both see into the details, and you&apos;ll be able to zoom out to see the system as a whole.&lt;/p&gt;
&lt;p&gt;That&apos;s why I&apos;ve modelled The Phases of Craftship process and curriculum in The Software Essentialist based on the natural process I&apos;ve noticed myself and others on their journey have taken as well.&lt;/p&gt;
&lt;p&gt;So in essence, the way to become a confident crafter is to embody a systems thinking perspective, but you have to go through certain experiences to develop it.&lt;/p&gt;
&lt;p&gt;There&apos;s so much more I&apos;d like to say about this, but I&apos;ll leave it here for now.&lt;/p&gt;
&lt;p&gt;Power &amp;#x26; love to you,
And as always,&lt;/p&gt;
&lt;p&gt;To Mastery
Khalil&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Tension Seeking Resolution (The Law of Polarity)]]></title><description><![CDATA[He holds out a rubber band, expands it until it snaps and says, “Tension seeking resolution. That’s it. That’s the key. The fundamental…]]></description><link>https://khalilstemmler.com/articles/tension-seeks-resolution/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/tension-seeks-resolution/</guid><pubDate>Fri, 25 Oct 2024 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;He holds out a rubber band, expands it until it snaps and says,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Tension seeking resolution. That’s it. That’s the key. The fundamental principle.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The instructor’s name was William Whitecloud.&lt;/p&gt;
&lt;p&gt;I thought about this lecture for months, which was a testament to the teaching itself.&lt;/p&gt;
&lt;h3 id=&quot;How-it-began&quot; style=&quot;position:relative;&quot;&gt;How it began&lt;a href=&quot;#How-it-began&quot; aria-label=&quot;How it began permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After the initial early adopter launch of &lt;a href=&quot;https://www.essentialist.dev/the-software-essentialist&quot;&gt;The Software Essentialist&lt;/a&gt;, I was pushing my mind to its limits to produce the initial batch of material for around 300 new students to play with.&lt;/p&gt;
&lt;p&gt;Yes, I wanted to do my best work, but I was not pacing myself properly.&lt;/p&gt;
&lt;p&gt;My family could feel it. &lt;/p&gt;
&lt;p&gt;My now ex girlfriend could feel it.&lt;/p&gt;
&lt;p&gt;And much like the rubber band, my mind was going to snap eventually.&lt;/p&gt;
&lt;p&gt;And it did.&lt;/p&gt;
&lt;p&gt;It felt like I had been hit by a car.&lt;/p&gt;
&lt;p&gt;I took a few weeks off to recover, because my body and my mind were clearly telling me to.&lt;/p&gt;
&lt;p&gt;When I returned, I studied leadership, self development, psychology, NLP, high performance, and spirituality.&lt;/p&gt;
&lt;p&gt;I learned more about myself during that period than any other time in my life.&lt;/p&gt;
&lt;p&gt;At some point along my path, I came across an image I hadn’t seen in a long time.&lt;/p&gt;
&lt;p&gt;I’m sure you know it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/tension-seeking-resolution/yin-yang.png&quot; alt=&quot;tension seeking resolution yin yang&quot;&gt;&lt;/p&gt;
&lt;p&gt;The yin-yang. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Well that’s profound, I thought.&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;I printed it out and kept it with me, because I knew there was something aptly important here.&lt;/p&gt;
&lt;h3 id=&quot;The-law-of-polarity&quot; style=&quot;position:relative;&quot;&gt;The law of polarity&lt;a href=&quot;#The-law-of-polarity&quot; aria-label=&quot;The law of polarity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Upon returning to recording the videos for the first version of what would today become &lt;a href=&quot;https://www.essentialist.dev/offers/bU72esPL/checkout?coupon_code=TESTING-MASTERY&quot;&gt;Testing Mastery&lt;/a&gt; and Best Practice Phase of Craftship material, I took note that of the fact that my work occurred differently to me.&lt;/p&gt;
&lt;p&gt;As I wrote a test, I began to notice something…&lt;/p&gt;
&lt;p&gt;When I wrote an empty test, I could feel a sort of &lt;em&gt;tension&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;It was different from the &lt;em&gt;psychological tension&lt;/em&gt; I experienced writing the code first, full well knowing that I’d be creating a temporary mess to later clean up.&lt;/p&gt;
&lt;p&gt;Instead, this &lt;em&gt;tension&lt;/em&gt; generated when I wrote an empty test. It seemed to create a vacuum — asking to be collapsed. &lt;/p&gt;
&lt;p&gt;A sort of &lt;em&gt;curiosity gap.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You know, because when you write an empty test…  when you Program By Wishful Thinking (my favourite Best Practice-First technique), sometimes, you have no idea how you’re going to make that test pass.&lt;/p&gt;
&lt;p&gt;And while I’ve always known that half of the work is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;upfront&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;top-down&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And the other half, of implementing the working code is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;emergent&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;bottom-up&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;…this time, instead of just &lt;em&gt;knowing&lt;/em&gt; these truths, I &lt;em&gt;understood&lt;/em&gt; them.&lt;/p&gt;
&lt;h3 id=&quot;The-Metaphysics&quot; style=&quot;position:relative;&quot;&gt;The Metaphysics&lt;a href=&quot;#The-Metaphysics&quot; aria-label=&quot;The Metaphysics permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&apos;ve observed something about reality: it&apos;s cyclical, multi-dimensional, and multi-perspectival.&lt;/p&gt;
&lt;p&gt;This will go above 85% of people&apos;s heads, but for any sort of long-term success, we really have to dig into this one a fair amount, because as Ray Dahlio says, &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Truth - more precisely, an accurate understanding of reality - is the essential foundation for producing good outcomes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Understand: every time you ask a question, write a test, make a plan, declare an estimate, commit to a new habit, or take on a goal to improve your life… you simultaneously commit to a temporary period of struggle.&lt;/p&gt;
&lt;p&gt;You encounter the inevitable tension seeking resolution.&lt;/p&gt;
&lt;p&gt;What a beautiful game of chaos and order we get to play.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;art of life&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;When expectation meets reality.&lt;/p&gt;
&lt;p&gt;To all you magicians who zig the zag and zag the zig.&lt;/p&gt;
&lt;p&gt;To &lt;strong&gt;Mastery&lt;/strong&gt;, I say to you.&lt;/p&gt;
&lt;h3 id=&quot;The-way-of-the-middle-path&quot; style=&quot;position:relative;&quot;&gt;The way of the middle path&lt;a href=&quot;#The-way-of-the-middle-path&quot; aria-label=&quot;The way of the middle path permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Imagine you&apos;re an entrepreneurial developer.&lt;/p&gt;
&lt;p&gt;You&apos;re ready to go all in again.&lt;/p&gt;
&lt;p&gt;So you quit your job with 12 months of savings, you identify a problem in the world that you want to solve, then you start to throw some code at it.&lt;/p&gt;
&lt;p&gt;You’re not guarding any of it with tests, but that’s okay. You know how this game goes.&lt;/p&gt;
&lt;p&gt;You stack more and more code.&lt;/p&gt;
&lt;p&gt;In other words, you stack more and more &lt;em&gt;tension&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Then you get your first customer.&lt;/p&gt;
&lt;p&gt;Relief, bliss, and then more tension. Why? &lt;/p&gt;
&lt;p&gt;Well, it’s &lt;em&gt;really&lt;/em&gt; on now.&lt;/p&gt;
&lt;p&gt;You keep on building.&lt;/p&gt;
&lt;p&gt;You hear the little voice say, &lt;em&gt;will this little project of mine work?&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;It seems like it will, because you just got another customer.&lt;/p&gt;
&lt;p&gt;Over the following weeks and months of building and refining, you start to notice:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it’s getting harder to add features&lt;/li&gt;
&lt;li&gt;the code is starting to feel overwhelming&lt;/li&gt;
&lt;li&gt;you have a fear of breaking something in a distant area of the codebase by changing code in another&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So what do you do? &lt;/p&gt;
&lt;p&gt;Well, you’ve validated your project already.&lt;/p&gt;
&lt;p&gt;So now you decide it’s time to cover that ground you’ve trodden with tests.&lt;/p&gt;
&lt;p&gt;You know the “right thing to do” would have been to have started with tests, but hey — this wasn’t guaranteed. You had no idea if any of this was going to amount to anything. &lt;/p&gt;
&lt;p&gt;If you were in an office and could expect a paycheque every month, you’d have probably taken a different path.&lt;/p&gt;
&lt;p&gt;Some BDD and TDD practitioners will tell you to &lt;em&gt;always&lt;/em&gt; start with the tests. Every scenario. &lt;/p&gt;
&lt;p&gt;But this is a very different game you’ve chosen to play.&lt;/p&gt;
&lt;p&gt;It requires a certain type of maturity to know how to keep the balance.&lt;/p&gt;
&lt;p&gt;But one thing is for certain: &lt;strong&gt;not knowing&lt;/strong&gt; &lt;strong&gt;how to write tests&lt;/strong&gt; &lt;em&gt;is a lot different&lt;/em&gt; from &lt;strong&gt;deciding not to&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;It took Eckhart Tolle&apos;s &lt;em&gt;The Power of Now&lt;/em&gt; for me to realize that reality is nothing but the present moment. &lt;/p&gt;
&lt;p&gt;In actuality, reality is but a continuous, perfect and harmonious hum of energy - an energy which continually balances itself out.&lt;/p&gt;
&lt;p&gt;There is no past, no future. That&apos;s all mind-generated stuff that the ego requires to maintain frames of perception and synchronize present moment behaviour.&lt;/p&gt;
&lt;p&gt;It has also become clear to me that we achieve outcomes within the universe using cycles.&lt;/p&gt;
&lt;p&gt;And when you write code, you start the cycle of tension (of stepping out of line with this continual stream of balanced energy), and you collapse that tension with a test.&lt;/p&gt;
&lt;p&gt;My friend. This is &lt;a href=&quot;https://khalilstemmler.com/articles/divergence-convergence-spaghetti-code/&quot;&gt;the creative process of divergence and convergence&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In my eyes, until you learn how to test as well as you can code, you are continually at odds with the law of polarity. &lt;/p&gt;
&lt;p&gt;You can sling messy code all you want, that&apos;s okay. Sometimes the situation calls for it.&lt;/p&gt;
&lt;p&gt;But expect the eventual slingshot of entropy. Expect that your code will come back to bite you.&lt;/p&gt;
&lt;p&gt;Because believe me, reality does not discriminate.&lt;/p&gt;
&lt;p&gt;My advice then is to learn how to test. &lt;/p&gt;
&lt;p&gt;Master it, then move on to the next skill to you need to collect to play the game of balance only accessible to those who know the rules.&lt;/p&gt;
&lt;p&gt;Because nothing in life is perfect.&lt;/p&gt;
&lt;p&gt;Seek not perfection. Seek the middle path.&lt;/p&gt;
&lt;p&gt;Of wu wei.&lt;/p&gt;
&lt;p&gt;Of effortless action.&lt;/p&gt;
&lt;p&gt;And dance with tension seeking resolution.&lt;/p&gt;
&lt;p&gt;Enjoy your week, and as always.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;To Mastery&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Two Categories of Tests: High Value vs. Typical Tests]]></title><description><![CDATA[Before we begin, You can join The Software Essentialist for an additional 15% off before we ship the Pattern-First phase of craftship. Use…]]></description><link>https://khalilstemmler.com/articles/high-value-typical-tests/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/high-value-typical-tests/</guid><pubDate>Fri, 16 Aug 2024 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Before we begin, You can &lt;a href=&quot;https://www.essentialist.dev/the-software-essentialist&quot;&gt;join The Software Essentialist for an additional 15% off&lt;/a&gt; before we ship the Pattern-First phase of craftship. Use the code TESTING-MASTERY before August 19th to join us in the course &amp;#x26; community&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;By now, you’re probably aware there’s a lot of different types of tests.&lt;/p&gt;
&lt;p&gt;Sure, we have unit, snapshot, component, so on &amp;#x26; so forth.&lt;/p&gt;
&lt;p&gt;But speak to anyone and you’ll hear that &lt;strong&gt;categorizing&lt;/strong&gt; the types of tests you write in the field can get kinda hairy.&lt;/p&gt;
&lt;p&gt;Some developers say “don’t worry about the &lt;em&gt;types&lt;/em&gt; of tests, just write tests”.&lt;/p&gt;
&lt;p&gt;Others say “write mostly integration tests” or “write e2e tests”.&lt;/p&gt;
&lt;p&gt;Getting the definitions down is a good place to start to answer “how TDD works in the real world”.&lt;/p&gt;
&lt;h2 id=&quot;What-well-cover&quot; style=&quot;position:relative;&quot;&gt;What we&apos;ll cover&lt;a href=&quot;#What-well-cover&quot; aria-label=&quot;What well cover permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this letter, we’re going to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✨ Learn what the main types of tests are &amp;#x26; why we need different ones anyway&lt;/li&gt;
&lt;li&gt;✨ Learn why test intent matters (&amp;#x26; why I first break tests into &lt;em&gt;high value customer-oriented&lt;/em&gt; vs. &lt;em&gt;typical developer type tests&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;✨ Understand the little known high value (acceptance) tests, how they work &amp;#x26; why they’re extremely powerful&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;What-are-the-different-types-of-test-categories&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;What are the different types of test categories?&lt;/strong&gt;&lt;a href=&quot;#What-are-the-different-types-of-test-categories&quot; aria-label=&quot;What are the different types of test categories permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The main test types that everyone is familiar with are unit, integration, and e2e.&lt;/p&gt;
&lt;p&gt;This is the scope at which most developers debate back and forth about tests, but I see it a bit differently.&lt;/p&gt;
&lt;p&gt;I believe it’s not enough to look at them like this — we have unit, integration, and e2e, of course, yes — but when we change our &lt;strong&gt;intent&lt;/strong&gt; behind the test, something interesting happens.&lt;/p&gt;
&lt;p&gt;For example, we can use unit tests, which we’ll learn are tests that run really fast — and which are typically just used to test something not all that life-changing or substantial like simple methods or utility classes...&lt;/p&gt;
&lt;p&gt;OR we can use them to test &lt;strong&gt;very valuable things&lt;/strong&gt;, like &lt;a href=&quot;https://wiki.solidbook.io/13-Features-(use-cases)-are-the-key-193ca4bbb8604c0eada33d1ac86ed517&quot;&gt;features&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For this reason, I group tests based on &lt;strong&gt;intent&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&quot;Are we writing tests for the &lt;strong&gt;customer&lt;/strong&gt; or for the &lt;strong&gt;developer&lt;/strong&gt;?&quot;&lt;/p&gt;
&lt;p&gt;And the answer to this tells us if our tests are &lt;strong&gt;typical tests&lt;/strong&gt; or if they are &lt;strong&gt;high value tests&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/high-value-typical-tests/high-value-typical-tests-1.png&quot; alt=&quot;High Value &amp;#x26; Typical Tests&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;Category-1-Typical-developer-oriented-tests&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Category #1: Typical (developer-oriented) tests&lt;/strong&gt;&lt;a href=&quot;#Category-1-Typical-developer-oriented-tests&quot; aria-label=&quot;Category 1 Typical developer oriented tests permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Typical tests: These are your e2e, unit &amp;#x26; integration tests — generally, every type of test can fit into one of these 3 broad types of tests. You’re probably somewhat familiar with these in at least some capacity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;Developer-oriented-tests-verify-technical-details&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Developer-oriented tests verify technical details&lt;/strong&gt;&lt;a href=&quot;#Developer-oriented-tests-verify-technical-details&quot; aria-label=&quot;Developer oriented tests verify technical details permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;What do I mean when I refer to &lt;em&gt;developer-oriented&lt;/em&gt; tests?&lt;/p&gt;
&lt;p&gt;Well, these are tests that are purely focused on ensuring that the &lt;strong&gt;internals&lt;/strong&gt; or some &lt;strong&gt;technical aspect&lt;/strong&gt; of our systems work properly.&lt;/p&gt;
&lt;p&gt;For example, tests like these are &lt;em&gt;developer-oriented tests&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Testing a date formatting utility&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; formatDate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;./formatDate&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;formatDate&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Test case 1: Simple date formatting&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; testDate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2021&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; expectedResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;March 12, 2021&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;formatDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;testDate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;expectedResult&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Test case 2: Formatting with time&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; testDateWithTime &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2021&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; expectedResultWithTime &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;March 12, 2021, at 4:30 PM&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;formatDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;testDateWithTime&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;expectedResultWithTime&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Test case 3: Handling invalid input&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; invalidDate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;not-a-date&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; expectedErrorMessage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Invalid date provided&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;formatDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;invalidDate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toThrowError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;expectedErrorMessage&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Testing that we can connect to the database*&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; models &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;./models&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Database connection&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should connect to the database&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sequelize&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;authenticate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeNull&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Verifying we can fetch data from an API (not a great test)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; jobsAPI &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;./jobsClient&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Jobs API client&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;fetches data from the jobs API&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fetchJobs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;items&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you guessed that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the first one was a &lt;strong&gt;unit test&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;the second one was an &lt;strong&gt;integration test&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;and the third one was also an &lt;strong&gt;integration test&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;… then you’d be right.&lt;/p&gt;
&lt;p&gt;And if you guessed wrong, that’s ok — we’ll learn about them next.&lt;/p&gt;
&lt;p&gt;But most importantly, what’s the &lt;strong&gt;intent&lt;/strong&gt; behind all of these tests?&lt;/p&gt;
&lt;p&gt;Who are we really &lt;strong&gt;supporting&lt;/strong&gt; by writing these tests?&lt;/p&gt;
&lt;p&gt;Ultimately, these are tests which are meant to validate technical things — &lt;em&gt;utilities, clients, classes, methods, functions, etc —&lt;/em&gt; and that makes them &lt;strong&gt;developer-oriented tests&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/high-value-typical-tests/high-value-typical-tests-2.png&quot; alt=&quot;High Value &amp;#x26; Typical Tests&quot;&gt;&lt;/p&gt;
&lt;p&gt;Coming back to Behaviour-Driven Design and the &lt;a href=&quot;https://khalilstemmler.com/letters/abstraction-the-feedback-loop-mental-models/&quot;&gt;&lt;em&gt;Abstraction Prism&lt;/em&gt;&lt;/a&gt;, developer-oriented tests are more-low level.&lt;/p&gt;
&lt;p&gt;Yes, we still need them, but they’re low level.&lt;/p&gt;
&lt;p&gt;And because they’re low level, they’re not as inherently &lt;strong&gt;valuable&lt;/strong&gt; as the tests which verify &lt;strong&gt;valuable outcomes.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;What do I mean by a valuable outcome?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;That’s it&lt;/em&gt;. The &lt;strong&gt;outcome&lt;/strong&gt; is the valuable thing — not the code. It’s the &lt;strong&gt;acceptance criteria&lt;/strong&gt;. The &lt;strong&gt;features&lt;/strong&gt;. The &lt;strong&gt;user stories&lt;/strong&gt;. And these come from the &lt;strong&gt;customer&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;There’s a fair amount of &lt;em&gt;distance&lt;/em&gt; between these &lt;em&gt;typical&lt;/em&gt; tests and these valuable abstraction layers.&lt;/p&gt;
&lt;p&gt;What’s the closest type of test to the user stories and acceptance criteria?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Acceptance tests&lt;/strong&gt;. In reality, customer-oriented tests are acceptance tests.&lt;/p&gt;
&lt;h2 id=&quot;Category-2-High-value-acceptance-tests&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Category #2: High value (acceptance) tests&lt;/strong&gt;&lt;a href=&quot;#Category-2-High-value-acceptance-tests&quot; aria-label=&quot;Category 2 High value acceptance tests permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;High value (acceptance) tests: These are tests which verify valuable customer/business outcomes. Commonly implemented as E2E tests, because they’re a subset of your typical tests, all typical can be written as high value acceptance tests. Done properly, a unit test can be a high value unit test. Done properly, an integration test can be a high value infrastructure test or an integration test.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;Customer-oriented-tests-verify-featuresacceptance-criteria&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Customer-oriented tests verify features/acceptance criteria&lt;/strong&gt;&lt;a href=&quot;#Customer-oriented-tests-verify-featuresacceptance-criteria&quot; aria-label=&quot;Customer oriented tests verify featuresacceptance criteria permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If developer-oriented tests support the developer, then acceptance tests are customer-oriented tests which support the customer.&lt;/p&gt;
&lt;p&gt;How? By giving them &lt;strong&gt;what they want&lt;/strong&gt;. The &lt;strong&gt;features&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For example, if the customer needed to synchronize their Notion Tasks to their Google Calendar, we could express the requirement with an &lt;strong&gt;acceptance test specification&lt;/strong&gt; like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;gherkin&quot;&gt;&lt;pre class=&quot;language-gherkin&quot;&gt;&lt;code class=&quot;language-gherkin&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# useCases/syncTasksToCalendar/SyncTasksToCalendar.feature&lt;/span&gt;

&lt;span class=&quot;token feature&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Feature:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Sync Notion tasks to Google Calendar&lt;/span&gt;

&lt;/span&gt;  &lt;span class=&quot;token scenario&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Scenario:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Sync new tasks&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token atrule&quot;&gt;Given&lt;/span&gt; there are tasks in my tasks database
    &lt;span class=&quot;token atrule&quot;&gt;And&lt;/span&gt; they don&apos;t exist in my calendar
    &lt;span class=&quot;token atrule&quot;&gt;When&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; sync my tasks database to my calendar
    &lt;span class=&quot;token atrule&quot;&gt;Then&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; should see them in my calendar&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And the test code would look something like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// useCases/syncTasksToCalendar/SyncTasksToCalendar.ts&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; defineFeature&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; loadFeature &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;jest-cucumber&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; path &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;path&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; SyncTasksToCalendar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./SyncTasksToCalendar&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; TasksDatabaseBuilder&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TasksDatabaseSpy &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../testUtils/tasksDatabaseBuilder&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; faker &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;faker&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; SyncServiceSpy &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../testUtils/syncServiceSpy&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ICalendarRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../services/calendar/calendarRepo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CalendarRepoBuilder &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../testUtils/calendarRepoBuilder&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; FakeClock &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../testUtils/fakeClock&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; DateUtil &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../../../shared/utils/DateUtil&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; feature &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loadFeature&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./SyncTasksToCalendar.feature&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;defineFeature&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;feature&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  letcalendarRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ICalendarRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  lettasksDatabaseSpy&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TasksDatabaseSpy&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  letsyncTasksToCalendar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; SyncTasksToCalendar&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  letsyncServiceSpy&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; SyncServiceSpy&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; fakeClock &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FakeClock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DateUtil&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2021&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;beforeEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    syncServiceSpy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SyncServiceSpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Sync new tasks&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; given&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; and&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; when&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; then &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;given&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;there are tasks in my tasks database&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      tasksDatabaseSpy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TasksDatabaseBuilder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;faker&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fakeClock&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withAFullWeekOfTasks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;they dont exist in my calendar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      calendarRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CalendarRepoBuilder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;faker&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withEmptyCalendar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Act&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;I sync my tasks database to my calendar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      syncTasksToCalendar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SyncTasksToCalendar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        tasksDatabaseSpy&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; calendarRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; syncServiceSpy
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; syncTasksToCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Assert&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;I should see them in my calendar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;syncServiceSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getSyncPlan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;creates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tasksDatabaseSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;countTasks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;syncServiceSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getSyncPlan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;updates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;syncServiceSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getSyncPlan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;deletes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Don’t worry about the various things in here you might not yet get like &lt;em&gt;Builders, Spies&lt;/em&gt; and whatnot.&lt;/p&gt;
&lt;p&gt;Just focus on the &lt;strong&gt;intent&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Hopefully it’s clear that if this works, it’s going to be a &lt;strong&gt;much, much more valuable&lt;/strong&gt; sort of test to the customer than a test against a text util class, right?&lt;/p&gt;
&lt;h2 id=&quot;Acceptance-tests-as-the-shared-single-source-of-truth-for-what-to-implement-on-any-side-of-the-stack&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Acceptance tests as the shared, single source of truth for what to implement on any side of the stack&lt;/strong&gt;&lt;a href=&quot;#Acceptance-tests-as-the-shared-single-source-of-truth-for-what-to-implement-on-any-side-of-the-stack&quot; aria-label=&quot;Acceptance tests as the shared single source of truth for what to implement on any side of the stack permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;“But Khalil, aren’t acceptance tests are supposed to verify the system from the perspective of the user? Does that mean we have to write them End to End?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Not necessarily.&lt;/p&gt;
&lt;p&gt;You can write &lt;strong&gt;acceptance tests&lt;/strong&gt; at the:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;e2e scope&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;unit testing scope&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;integration testing scope&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;AND&lt;/strong&gt; you can use the same test and execute it on the frontend, backend, desktop, mobile, wherever.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Check out this beautiful image again. You’ll need to enlarge it to see it properly.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/high-value-typical-tests/high-value-typical-tests-3.png&quot; alt=&quot;High Value &amp;#x26; Typical Tests&quot;&gt;&lt;/p&gt;
&lt;p&gt;Allow me to explain.&lt;/p&gt;
&lt;p&gt;First, it starts by building the acceptance testing rig — which is the common denominator.&lt;/p&gt;
&lt;h3 id=&quot;The-acceptance-test-rig&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;The acceptance test rig&lt;/strong&gt;&lt;a href=&quot;#The-acceptance-test-rig&quot; aria-label=&quot;The acceptance test rig permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The acceptance test rig is a necessary component we need to write our high value tests of any sort.&lt;/p&gt;
&lt;p&gt;Whenever we cross &lt;strong&gt;architectural boundaries&lt;/strong&gt;, we need 4 layers to set up our work in cohesive way.&lt;/p&gt;
&lt;p&gt;Those 4 layers are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The Acceptance Test Layer&lt;/strong&gt; — this is where we write our acceptance tests&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Executable Specification Layer&lt;/strong&gt; — this is your test code (ie: jest)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Domain Specific Language Layer&lt;/strong&gt; — this is where you focus on expressing &lt;strong&gt;what&lt;/strong&gt;, not how&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Protocol Driver Layer&lt;/strong&gt; — this is where we express the &lt;strong&gt;how&lt;/strong&gt; to implement the &lt;strong&gt;what&lt;/strong&gt; (ie: when we cross architectural boundaries, we often need this final layer to translate the domain language layer instructions into &lt;strong&gt;HTTP calls, GraphQL calls, console instructions, or browser clicks or button presses&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/high-value-typical-tests/high-value-typical-tests-4.png&quot; alt=&quot;High Value &amp;#x26; Typical Tests&quot;&gt;&lt;/p&gt;
&lt;p&gt;These 4 layers work together to spread out the process involved in translating an English looking acceptance test into real-life interactions.&lt;/p&gt;
&lt;h2 id=&quot;Acceptance-tests-are-the-single-source-of-truth&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Acceptance tests are the single source of truth&lt;/strong&gt;&lt;a href=&quot;#Acceptance-tests-are-the-single-source-of-truth&quot; aria-label=&quot;Acceptance tests are the single source of truth permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Regardless of the scope, the single source of truth is the &lt;strong&gt;acceptance test&lt;/strong&gt; for all scopes.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/high-value-typical-tests/high-value-typical-tests-5.png&quot; alt=&quot;High Value &amp;#x26; Typical Tests&quot;&gt;&lt;/p&gt;
&lt;p&gt;Yet again, this is the power of contracts.&lt;/p&gt;
&lt;p&gt;If a customer asks for a new feature, well, both the frontend &lt;strong&gt;and&lt;/strong&gt; the backend can treat that acceptance test as a &lt;strong&gt;contract&lt;/strong&gt; and implement the desired behaviour — albeit in different &lt;em&gt;ways&lt;/em&gt;, with different tasks, but they implement it.&lt;/p&gt;
&lt;h2 id=&quot;Why-is-it-so-important-to-know-how-to-write-high-value-tests&quot; style=&quot;position:relative;&quot;&gt;Why is it so important to know how to write high value tests?&lt;a href=&quot;#Why-is-it-so-important-to-know-how-to-write-high-value-tests&quot; aria-label=&quot;Why is it so important to know how to write high value tests permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;We are what we repeatedly do. Excellence, then, is not an act, but a habit.&quot; - Aristotle&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I used to pride myself in the ability to make something work &lt;em&gt;once&lt;/em&gt;, but that doesn&apos;t impress me at all anymore.&lt;/p&gt;
&lt;p&gt;Building products and writing code in such a way that you can &lt;em&gt;continue&lt;/em&gt; to stack value on top of value... &lt;/p&gt;
&lt;p&gt;Past a certain threshold, it is &lt;strong&gt;HARD&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;And if you know my story, you know I had to learn the hard way.&lt;/p&gt;
&lt;p&gt;As I&apos;ve covered in &quot;&lt;a href=&quot;/letters/divergence-convergence-spaghetti-code/&quot;&gt;Why You Have Spaghetti Code&lt;/a&gt;&quot;, value creation is a zig-zag act of divergence-convergence. &lt;/p&gt;
&lt;p&gt;It&apos;s a game of &lt;em&gt;vector dynamics&lt;/em&gt; if you will. &lt;/p&gt;
&lt;p&gt;You set a target, not entirely sure how you&apos;ll get there, and then you bridge the gap with code. That&apos;s what we&apos;re doing with tests. Your tests are the vector conditions. Your code is the bridge.&lt;/p&gt;
&lt;p&gt;Developers that know how to do this, either at the start of a feature, or after the fact (ie: &lt;a href=&quot;https://khalilstemmler.com/letters/legacy-code/&quot;&gt;producing value for a company by cleaning up technical dept&lt;/a&gt; in a slow, consistent manner)...&lt;/p&gt;
&lt;p&gt;I think these devs are those that stand the most likely chance of not only standing out to get the best jobs and opportunities, but to actually &lt;strong&gt;thrive in them as well&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;So yeah, all the easy stuff is... &lt;em&gt;easy&lt;/em&gt; 😂. &lt;/p&gt;
&lt;p&gt;Anyone can write code. &lt;/p&gt;
&lt;p&gt;But solving business problems?&lt;/p&gt;
&lt;p&gt;That&apos;s a metaphysical game. It&apos;s a whole different level, man.&lt;/p&gt;
&lt;h2 id=&quot;How-to-get-started&quot; style=&quot;position:relative;&quot;&gt;How to get started?&lt;a href=&quot;#How-to-get-started&quot; aria-label=&quot;How to get started permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In my opinion, the best type of testing you should practice are the tests against features.&lt;/p&gt;
&lt;p&gt;But you kinda need to &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/introduction-to-tdd/&quot;&gt;master the basics - the physical mechanics of TDD first&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;https://www.essentialist.dev/the-software-essentialist&quot;&gt;The Software Essentialist&lt;/a&gt;, we go through a ton of exercises to really drill this skillset down to prepare you for the hard stuff.&lt;/p&gt;
&lt;p&gt;So start with basic TDD exercises first. &lt;/p&gt;
&lt;p&gt;Once you feel like you&apos;re comfortable there, move onto the more complicated high value tests that we use to refactor legacy code and &lt;a href=&quot;/letters/using-builders-for-complex-test-states/&quot;&gt;contractualize the complex test states that comes with the territory&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There&apos;s so much more, but just take the first step and start figuring it out.&lt;/p&gt;
&lt;p&gt;Because the paradox of mastering testing, is that once you master testing, you master vector dynamics.&lt;/p&gt;
&lt;p&gt;And if you master vector dynamics, you&apos;re mastering goal achievement.&lt;/p&gt;
&lt;p&gt;And if you master goal achievement, well then nothing can stop you, really.&lt;/p&gt;
&lt;h2 id=&quot;Summary&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;a href=&quot;#Summary&quot; aria-label=&quot;Summary permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In summary, there are a number of different types of tests we can use (on any side of the stack).&lt;/p&gt;
&lt;p&gt;I generalize them as the &lt;strong&gt;typical tests&lt;/strong&gt; and the High Value (Acceptance) Tests.&lt;/p&gt;
&lt;p&gt;We write tests primarily for the &lt;strong&gt;customer&lt;/strong&gt; or for the &lt;strong&gt;developer&lt;/strong&gt;, and differentiate tests based on the &lt;em&gt;concerns/abstraction layers&lt;/em&gt; they validate.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Power &amp;#x26; love to you, my friend.&lt;/p&gt;
&lt;p&gt;And as always,&lt;/p&gt;
&lt;p&gt;To Mastery.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Using Builders to Model Complex Test States]]></title><description><![CDATA[In a recent letter, I explained that edge cases can be an absolute nightmare to deal with when testing testing features. To deal with this…]]></description><link>https://khalilstemmler.com/articles/using-builders-for-complex-test-states/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/using-builders-for-complex-test-states/</guid><pubDate>Thu, 15 Aug 2024 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;In &lt;a href=&quot;https://www.essentialist.dev/e/BAh7BjoWZW1haWxfZGVsaXZlcnlfaWRsKwjN9TykBQA%3D--d3d269d402fb06c9ab9c6ff48dad5d4722d66740?skip_click_tracking=true&quot;&gt;a recent letter&lt;/a&gt;, I explained that edge cases can be an absolute nightmare to deal with when testing testing features.&lt;/p&gt;
&lt;p&gt;To deal with this, we learned that there are 2 general techniques at your disposal:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;randomness (which sometimes works)&lt;/li&gt;
&lt;li&gt;resetting and constructing the test state (which always works)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Admittedly, #1 is super easy, and that’s why it only sometimes works for simple cases.&lt;/p&gt;
&lt;p&gt;But #2… well this is hard, but it &lt;strong&gt;always works&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In this letter, I’ll gift you the gift of how to use #2 — you’ll learn how to use my favourite testing pattern — the builder pattern.&lt;/p&gt;
&lt;p&gt;But first, why exactly is it so hard to set up test states?&lt;/p&gt;
&lt;h2 id=&quot;Why-is-it-so-hard-to-set-up-test-states&quot; style=&quot;position:relative;&quot;&gt;Why is it so hard to set up test states?&lt;a href=&quot;#Why-is-it-so-hard-to-set-up-test-states&quot; aria-label=&quot;Why is it so hard to set up test states permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To illustrate, let’s return to the &lt;em&gt;School&lt;/em&gt; domain.&lt;/p&gt;
&lt;p&gt;And then let’s imagine we wanted to test the &lt;strong&gt;create class room&lt;/strong&gt; feature. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;gherkin&quot;&gt;&lt;pre class=&quot;language-gherkin&quot;&gt;&lt;code class=&quot;language-gherkin&quot;&gt;&lt;span class=&quot;token feature&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Feature:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Create Class Room&lt;/span&gt;

    As an administrator
    I want to create a class
    So that I can add students to it

&lt;/span&gt;    &lt;span class=&quot;token scenario&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Scenario:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Successfully create a class room&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token atrule&quot;&gt;Given&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; want to create a class room named &lt;span class=&quot;token string&quot;&gt;&quot;Math&quot;&lt;/span&gt;
        &lt;span class=&quot;token atrule&quot;&gt;When&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; send a request to create a class room
        &lt;span class=&quot;token atrule&quot;&gt;Then&lt;/span&gt; the class room should be created successfully&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Recall that it’s easy to test success scenario because to set up the test state, all we have to do is wipe out the database or use randomness to make our tests idempotent again.&lt;/p&gt;
&lt;p&gt;For example, we don’t want to trigger the &lt;strong&gt;unique constraint&lt;/strong&gt; on the name field (because you can’t have two classes named “Math”).&lt;/p&gt;
&lt;p&gt;But what about the following scenario? How would you test this?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;gherkin&quot;&gt;&lt;pre class=&quot;language-gherkin&quot;&gt;&lt;code class=&quot;language-gherkin&quot;&gt;&lt;span class=&quot;token feature&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Feature:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Create Class Room&lt;/span&gt;

...
        
&lt;/span&gt;    &lt;span class=&quot;token scenario&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Scenario:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Classroom already exists&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token atrule&quot;&gt;Given&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;a&lt;/span&gt; classroom already exists
        &lt;span class=&quot;token atrule&quot;&gt;When&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; send a request to create a class room of the same name
        &lt;span class=&quot;token atrule&quot;&gt;Then&lt;/span&gt; the class room should not be created&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ah, the classroom already exists…&lt;/p&gt;
&lt;p&gt;Well, of course, like always, you’d start by representing it in the executable specification, of course.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Classroom already exists&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; given&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; when&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; then &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; classroomName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Science&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; requestBody&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; classroomName
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; response&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;given&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;a classroom already exists&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// ??&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;I send a request to create a class room of the same name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/classes&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;requestBody&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;the class room should not be created&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;success&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeFalsy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ServerError&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But how do you model the fact that the classroom already exists? &lt;/p&gt;
&lt;p&gt;Do we just call the create classroom API twice? &lt;/p&gt;
&lt;p&gt;Do you write a function to “create the classroom” beforehand?&lt;/p&gt;
&lt;p&gt;It seems reasonable, but when you follow that line of thinking and working to extremes, it actually results in a lot of confusing code prone to duplication.&lt;/p&gt;
&lt;p&gt;Honestly, this is something I used to find extremely difficult.&lt;/p&gt;
&lt;p&gt;We want to know how to compose the database test state &lt;em&gt;properly.&lt;/em&gt; I prefer to hold a root level understanding, when I can, so let me introduce you to what I believe is a &lt;strong&gt;foundational&lt;/strong&gt; concept — a &lt;strong&gt;first principle&lt;/strong&gt;, if you will.&lt;/p&gt;
&lt;p&gt;It may very well have a different name, but I call it &lt;em&gt;The Data Model Tree&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;The-Data-Model-Tree&quot; style=&quot;position:relative;&quot;&gt;The Data Model Tree&lt;a href=&quot;#The-Data-Model-Tree&quot; aria-label=&quot;The Data Model Tree permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.essentialist.dev/the-software-essentialist&quot;&gt;In a vital lesson on composition in The Software Essentialist&lt;/a&gt;, I explain that your application is a web of objects (or a tree). &lt;/p&gt;
&lt;p&gt;We see this when we link dependencies and bootstrap our applications.&lt;/p&gt;
&lt;p&gt;But the phenomenon actually extends far beyond just how we connect classes and functions.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;Data Model Tree&lt;/em&gt; is the relationship between all of your data models in your database. &lt;/p&gt;
&lt;p&gt;And they too, come together to form a tree in their sequence of creation.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/builders/data-model-tree-1.png&quot; alt=&quot;Data Model Tree&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;You-have-to-reconstruct-the-tree-to-test-scenarios&quot; style=&quot;position:relative;&quot;&gt;You have to reconstruct the tree to test scenarios&lt;a href=&quot;#You-have-to-reconstruct-the-tree-to-test-scenarios&quot; aria-label=&quot;You have to reconstruct the tree to test scenarios permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Here’s what makes setting up your database for your tests so complex: &lt;strong&gt;you have to re-create the entire tree&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Wait, what?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Look: say I want to test a feature in our School domain called &lt;strong&gt;gradeAssignment&lt;/strong&gt;. To write this test, all of the side-effects of grade assignment to have already happened.&lt;/p&gt;
&lt;p&gt;To begin this process, I’d first ask: “what is the state of the data models at the point I want to grade an assignment?”&lt;/p&gt;
&lt;p&gt;Well, in order for a teacher to &lt;strong&gt;grade&lt;/strong&gt; an assignment, it would need to have first been &lt;strong&gt;assigned to a student&lt;/strong&gt;, right?&lt;/p&gt;
&lt;p&gt;And to get all the way up to this point in the sequence of creation, it’d mean:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;first, the &lt;strong&gt;classroom&lt;/strong&gt; and &lt;strong&gt;the student&lt;/strong&gt; need to exist&lt;/li&gt;
&lt;li&gt;then, once this is true, I need to then link the student to the classroom using &lt;strong&gt;a student enrolment&lt;/strong&gt; record&lt;/li&gt;
&lt;li&gt;then I’d create &lt;strong&gt;an assignment&lt;/strong&gt; for the classroom, because it directly relied upon the existence of a classroom&lt;/li&gt;
&lt;li&gt;from here, I’d now assign the &lt;strong&gt;assignment&lt;/strong&gt; to the student, linking together the &lt;strong&gt;enrolledStudent&lt;/strong&gt; and the &lt;strong&gt;assignment&lt;/strong&gt;, creating a &lt;strong&gt;studentAssignment&lt;/strong&gt; record&lt;/li&gt;
&lt;li&gt;then, the student has to &lt;strong&gt;submit an assignment&lt;/strong&gt;, creating an &lt;strong&gt;assignmentSubmission&lt;/strong&gt; record&lt;/li&gt;
&lt;li&gt;then, and ONLY then, can I, the teacher, grade the assignment, creating a &lt;strong&gt;grade&lt;/strong&gt; record&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;OH MY GOD.&lt;/p&gt;
&lt;p&gt;So your head doesn’t explode: look. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Here’s the sequence of data models required to run this test.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/builders/data-model-tree-2.png&quot; alt=&quot;Data Model Tree&quot;&gt;&lt;/p&gt;
&lt;p&gt;Sound like a lot of work?&lt;/p&gt;
&lt;p&gt;I’m making it out to sound worse than it is.&lt;/p&gt;
&lt;p&gt;It’s not that bad. &lt;/p&gt;
&lt;p&gt;But you know how I talk about &lt;em&gt;aligning your actions with the nature of reality&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;Yeah, well, this is where data comes from. &lt;/p&gt;
&lt;p&gt;It emerges in little chunks and pieces like this.&lt;/p&gt;
&lt;p&gt;The plus side: This is about as hard as it gets. Everything is so much easier (especially &lt;strong&gt;aggregate design in &lt;a href=&quot;https://khalilstemmler.com/articles/domain-driven-design-intro/&quot;&gt;domain-driven design&lt;/a&gt;&lt;/strong&gt;) when you understand this and think about your data as if you’re building bits and pieces of trees with each API call and operation.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.essentialist.dev/the-software-essentialist&quot;&gt;As a side note, you can join The Software Essentialist for an additional 15% off before I ship the Pattern-First phase of craftship. Use the code TESTING-MASTERY before August 19th to join us in the course &amp;#x26; community&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;You-have-to-reconstruct-the-tree-in-reverse&quot; style=&quot;position:relative;&quot;&gt;You have to reconstruct the tree in reverse&lt;a href=&quot;#You-have-to-reconstruct-the-tree-in-reverse&quot; aria-label=&quot;You have to reconstruct the tree in reverse permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Listen, I know you know how trees work.&lt;/p&gt;
&lt;p&gt;I’ve been in leetcode hell, myself 😂&lt;/p&gt;
&lt;p&gt;In case you forgot, we’ve got a root, leaf nodes, intermediate nodes, branches, and traversals.&lt;/p&gt;
&lt;p&gt;“Why are you triggering my PTSD right now, Khalil. Are you that sick and twisted?”&lt;/p&gt;
&lt;p&gt;Not intentionally..&lt;/p&gt;
&lt;p&gt;Look. Here’s why I bring up trees:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Each test state has at least one Target Data Model in focus&lt;/strong&gt;, and &lt;strong&gt;to prepare your database state for the test,&lt;/strong&gt; you have to create the entire structure of the tree in reverse, from that &lt;strong&gt;Target Data Model&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Pause on that one and read it again.&lt;/p&gt;
&lt;p&gt;It can be confusing, but it’s the key.&lt;/p&gt;
&lt;p&gt;To illustrate, let’s see some examples.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example #1: If I was testing “assign student to a class” (ie: to create an enrolment), the Target Data Model is “EnrolledStudent” means I first need to have:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;created the student and the class&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Therefore, your tree setup should look like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/builders/data-model-tree-3.png&quot; alt=&quot;Data Model Tree&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example #2: If I were testing “createAssignment”, the Target Data Model is “Assignment”, which that means I need to have first:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;created a classroom&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And thus, like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/builders/data-model-tree-4.png&quot; alt=&quot;Data Model Tree&quot;&gt;&lt;/p&gt;
&lt;p&gt;In this case, you don’t need to create students or anything else because you don’t need to create a student to get up the tree to the classroom. &lt;/p&gt;
&lt;p&gt;Can you see how an understanding of the data model is required to do this work? &lt;/p&gt;
&lt;p&gt;Another example.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example #3: If I were testing “grading an assignment, the Target Data Model is “GradedAssignment”, which means I need to have first:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;created the student and the class&lt;/li&gt;
&lt;li&gt;enrolled the student to the class&lt;/li&gt;
&lt;li&gt;created the assignment&lt;/li&gt;
&lt;li&gt;created a student assignment&lt;/li&gt;
&lt;li&gt;created a student assignment submission&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/builders/data-model-tree-5.png&quot; alt=&quot;Data Model Tree&quot;&gt;&lt;/p&gt;
&lt;p&gt;That’s the most complex one.&lt;/p&gt;
&lt;p&gt;But if you get this, you are golden, my friend.&lt;/p&gt;
&lt;p&gt;If you don’t get it yet, that’s cool. There’s a massive difference between knowledge &amp;#x26; experience. You need practice. We do a lot of that in &lt;a href=&quot;https://www.essentialist.dev/the-software-essentialist&quot;&gt;the course&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;“That’s cool and all, Khalil. But how do you ACTUALLY set this up for a test? It seems like it’s going to be some sort of complex graph and trees traversal stuff.”&lt;/p&gt;
&lt;p&gt;It’s actually &lt;strong&gt;very straightforward&lt;/strong&gt; if you follow a few design principles and patterns.&lt;/p&gt;
&lt;p&gt;I’ll show ya the pattern first.&lt;/p&gt;
&lt;p&gt;Let’s see the tremendous Builder Pattern.&lt;/p&gt;
&lt;h2 id=&quot;What-are-builders&quot; style=&quot;position:relative;&quot;&gt;What are builders?&lt;a href=&quot;#What-are-builders&quot; aria-label=&quot;What are builders permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As I said, The Builder Pattern is one of my favourites.&lt;/p&gt;
&lt;p&gt;Builders help you construct values, implement relationships, and set up your test states in an extremely readable, expressive, declarative and domain-driven way. And that’s what I’m all about — the link between TDD, DDD, great design and great DX.&lt;/p&gt;
&lt;p&gt;So, for example, let’s say we wanted to create a student as a pre-condition for a test.&lt;/p&gt;
&lt;p&gt;While we can design these to construct just pure objects, we’re going to need to design our builders to manipulate the database for us. Usage of such a builder that sets up the database state might look like this from the outside.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; studentBuilder &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;StudentBuilder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; studentBuilder
	&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Jackson&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withRandomEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And on the inside, it might look like the following.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;StudentBuilder&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Partial&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;StudentProps&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;;

  constructor() &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    
  withName(name) &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  
  withRandomEmail() &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; faker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;internet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  
  async build() &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; student &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; prisma&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;student&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; student&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pretty nifty, eh?&lt;/p&gt;
&lt;p&gt;It’s the chaining that I like the most.&lt;/p&gt;
&lt;h2 id=&quot;How-to-design-builders-practical-tips&quot; style=&quot;position:relative;&quot;&gt;How to design builders? (practical tips)&lt;a href=&quot;#How-to-design-builders-practical-tips&quot; aria-label=&quot;How to design builders practical tips permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This letter is running pretty long again, so let’s get practical.&lt;/p&gt;
&lt;p&gt;What I’ve found is this: the best way to build builders is to follow the laws of &lt;em&gt;The Data Model Tree&lt;/em&gt;, and to work in reverse starting from target data model, constructing the test state using the SPECIFIC keywords: &lt;strong&gt;build, from, and&lt;/strong&gt; and &lt;strong&gt;with&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here’s what I mean.&lt;/p&gt;
&lt;h2 id=&quot;Demonstration&quot; style=&quot;position:relative;&quot;&gt;Demonstration&lt;a href=&quot;#Demonstration&quot; aria-label=&quot;Demonstration permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let’s do “assign a student to an assignment”. &lt;/p&gt;
&lt;p&gt;This is a real tricky one.&lt;/p&gt;
&lt;p&gt;But it’s easy if we focus on one layer of abstraction at a time. &lt;/p&gt;
&lt;p&gt;First layer? The acceptance test.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;gherkin&quot;&gt;&lt;pre class=&quot;language-gherkin&quot;&gt;&lt;code class=&quot;language-gherkin&quot;&gt;&lt;span class=&quot;token feature&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Feature:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Assign an assignment to a student&lt;/span&gt;

    As a teacher
    I want to assign a student to an assignment
    So that the student can achieve learning objectives

&lt;/span&gt;    &lt;span class=&quot;token scenario&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Scenario:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Assign a student to an assignment&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token atrule&quot;&gt;Given&lt;/span&gt; there is an existing student enrolled to a class
        &lt;span class=&quot;token atrule&quot;&gt;And&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;an&lt;/span&gt; assignment exists for the class
        &lt;span class=&quot;token atrule&quot;&gt;When&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; assign the student the assignment 
        &lt;span class=&quot;token atrule&quot;&gt;Then&lt;/span&gt; the student should be assigned to the assignment&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What needs to first exist in order to do this?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;the student must first be enrolled to the class&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;the assignment must first exist&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So we need to model those, in the executable specification.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Assign a student to an assignment&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    given&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    when&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    and&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    then&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; requestBody&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; response&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;beforeAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;resetDatabase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;given&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;there is an existing student enrolled to a class&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;an assignment exists for the class&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now, for each of these pre-condition clauses, the question is: “what’s the &lt;strong&gt;Target Data Model&lt;/strong&gt;?”&lt;/p&gt;
&lt;p&gt;Well let’s see. Let’s do the first one. &lt;/p&gt;
&lt;p&gt;For the &lt;code class=&quot;language-text&quot;&gt;Given&lt;/code&gt;, it appears we’re dealing with an &lt;strong&gt;enrollment&lt;/strong&gt; right? “a student is enrolled to a class”. Yep. And what’s the relationship? &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;an enrolment&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;comes from a student&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;with a name&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;with an email&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;and from a classroom&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;with a name&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Makes sense, right?&lt;/p&gt;
&lt;p&gt;How would you model that using a Builder?&lt;/p&gt;
&lt;p&gt;Like this.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token function&quot;&gt;given&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;there is an existing student enrolled to a class&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; enrollmentResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; studentEnrollmentBuilder
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromClassroom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;classroomBuilder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withClassName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Math&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;studentBuilder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Johnny&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;student@example.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    student &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; enrollmentResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;student&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And putting it all together?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Assign a student to an assignment&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    given&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    when&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    and&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    then&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; requestBody&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; response&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; student&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Student&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; assignment&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Assignment&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;beforeAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;resetDatabase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;given&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;there is an existing student enrolled to a class&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; enrollmentResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; studentEnrollmentBuilder
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromClassroom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;classroomBuilder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withClassName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Math&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;studentBuilder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Johnny&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;johnny@example.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    student &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; enrollmentResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;student&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;an assignment exists for the class&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    assignment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; assignmentBuilder
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromClassroom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;classroomBuilder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withClassName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Math&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Boom 💥 &lt;/p&gt;
&lt;p&gt;Notice the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I use the word &lt;em&gt;with&lt;/em&gt; to express &lt;strong&gt;fields/values&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;I use the word &lt;em&gt;from&lt;/em&gt; and &lt;em&gt;and&lt;/em&gt; to express &lt;strong&gt;relationships&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;I use the word &lt;strong&gt;build&lt;/strong&gt; to construct it all&lt;/li&gt;
&lt;li&gt;I focus on the end result, the thing I really want to build — which is the &lt;strong&gt;enrolment&lt;/strong&gt;, and I assume that it will work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That’s the magic, my friend.&lt;/p&gt;
&lt;p&gt;And if you like that, we can continue to improve it like so: &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Assign a student to an assignment&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    given&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    when&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    and&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    then&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; requestBody&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; response&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; student&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Student&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; assignment&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Assignment&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;beforeAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;resetDatabase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;given&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;there is an existing student enrolled to a class&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; enrollmentResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;anEnrolledStudent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;aClassRoom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withClassName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Math&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;aStudent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Johnny&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;johnny@example.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    student &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; enrollmentResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;student&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;an assignment exists for the class&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    assignment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;anAssignment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;aClassRoom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withClassName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Math&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Wonderful, wonderful stuff.&lt;/p&gt;
&lt;p&gt;I’ll break this down more in future letters.&lt;/p&gt;
&lt;p&gt;Happy testing!&lt;/p&gt;
&lt;p&gt;And as always,
To Mastery&lt;/p&gt;
&lt;p&gt;Khalil&lt;/p&gt;
&lt;p&gt;PS: &lt;a href=&quot;https://www.essentialist.dev/the-software-essentialist&quot;&gt;As reminder, you can join us in The Software Essentialist for an additional 15% off using the code TESTING-MASTERY before August 19th&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to Improve Legacy Code w/ Characterization Tests]]></title><description><![CDATA[Ever been so scared to change your code out of fear you’ll break something? You’re not alone. Been there. Over the last months, I’ve been…]]></description><link>https://khalilstemmler.com/articles/legacy-code/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/legacy-code/</guid><pubDate>Mon, 12 Aug 2024 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Ever been so scared to change your code out of fear you’ll break something?&lt;/p&gt;
&lt;p&gt;You’re not alone.&lt;/p&gt;
&lt;p&gt;Been there.&lt;/p&gt;
&lt;p&gt;Over the last months, I’ve been hella busy with &lt;a href=&quot;https://www.essentialist.dev/the-software-essentialist&quot;&gt;The Software Essentialist&lt;/a&gt; and the first edition of solidbook, but I wanted to take a minute to address this common question, which is:&lt;/p&gt;
&lt;p&gt;How do you deal with legacy code? How can you get started improving it safely?&lt;/p&gt;
&lt;p&gt;And it’s a great question.&lt;/p&gt;
&lt;p&gt;If you asked me way back when I first started out, I would have thought to look to Domain Driven-Design and how to refactor from unstructured to structured code.&lt;/p&gt;
&lt;p&gt;I’d have opted for tools like Event Storming and Event Modelling to think through the design properly and re-write it.&lt;/p&gt;
&lt;p&gt;And while that stuff is cool and essential (in a separate phase), there’s actually a more important stage first, and it’s not sexy.&lt;/p&gt;
&lt;p&gt;You’ve got to characterize your code, mate.&lt;/p&gt;
&lt;p&gt;Which (and I know you don&apos;t wanna hear this, because I also didn&apos;t want to back then) means learning how to write decent tests first 😂 .&lt;/p&gt;
&lt;h2 id=&quot;Tests-are-the-key-to-entropy-reversal&quot; style=&quot;position:relative;&quot;&gt;Tests are the key to entropy reversal&lt;a href=&quot;#Tests-are-the-key-to-entropy-reversal&quot; aria-label=&quot;Tests are the key to entropy reversal permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you’ve read the early drafts of solidbook, you’ll recall that I talk about entropy — a naturally occurring phenomenon whereby the universe has a tendency towards complexity. Chaos. Disorder.&lt;/p&gt;
&lt;p&gt;You know, the dishes piling up in the sink.&lt;/p&gt;
&lt;p&gt;Your plans with friends getting cancelled because someone caught the flu.&lt;/p&gt;
&lt;p&gt;That’s life. Things get messy.&lt;/p&gt;
&lt;p&gt;And as a wise man with a long grey beard probably once said,&lt;/p&gt;
&lt;p&gt;“It is what it is.”&lt;/p&gt;
&lt;p&gt;Well, over the years on my search for the answer to “how to write scalable, testable, flexible code”, I paid more attention to metaphysics and how reality tends to work.&lt;/p&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;p&gt;It’s like what Ray Dahlio says in his excellent book Principles,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Truth — more precisely, an accurate understanding of reality — is the essential foundation for producing good outcomes.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Before I discovered my own set of principles which would eventually become The 12 Essentials that guide literally everything we do in The Software Essentialist, I learned that tests (or more generally — contracts) are the initial key to reversing entropy.&lt;/p&gt;
&lt;p&gt;In other words, if you want to make your code better, it’s always going to start with a layer of code that documents what’s coming in the next layer of code.&lt;/p&gt;
&lt;p&gt;And that’s a test.&lt;/p&gt;
&lt;h2 id=&quot;Characterization-tests&quot; style=&quot;position:relative;&quot;&gt;Characterization tests&lt;a href=&quot;#Characterization-tests&quot; aria-label=&quot;Characterization tests permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First of all, let’s clarify.&lt;/p&gt;
&lt;p&gt;What’s legacy code?&lt;/p&gt;
&lt;p&gt;I’m paraphrasing Michael Feathers when he says that “legacy code is code without tests”.&lt;/p&gt;
&lt;p&gt;That’s a sharp distinction, but it makes sense to me.&lt;/p&gt;
&lt;p&gt;What is a characterization test?&lt;/p&gt;
&lt;p&gt;Simply, it’s a test that you write after the fact.&lt;/p&gt;
&lt;p&gt;Basically, it’s a test against legacy code.&lt;/p&gt;
&lt;p&gt;And what do we do?&lt;/p&gt;
&lt;p&gt;We determine the characteristics of the codebase as it is, and we lay down tests that express the behaviour.&lt;/p&gt;
&lt;p&gt;Why? It stabilizes the codebase so that you can do more invasive things moving forward.&lt;/p&gt;
&lt;p&gt;It’s kinda like a tailor putting pins in your jacket and checking with you before cutting into the fabric.&lt;/p&gt;
&lt;p&gt;“Let’s just make sure it’s right before we continue.”&lt;/p&gt;
&lt;p&gt;Characterization tests merely document what the code already does.&lt;/p&gt;
&lt;p&gt;Lemme show you how it works.&lt;/p&gt;
&lt;h2 id=&quot;Example-code&quot; style=&quot;position:relative;&quot;&gt;Example code&lt;a href=&quot;#Example-code&quot; aria-label=&quot;Example code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let’s consider an example shall we?&lt;/p&gt;
&lt;p&gt;Imagine a Classroom System domain. And imagine it was all written in a messy index.ts or something.&lt;/p&gt;
&lt;p&gt;Here’s a submitAssignment API call.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// POST student submitted assignment&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/student-assignments/submit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
	&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isMissingKeys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;assignmentId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;studentId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Errors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ValidationError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        success&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; studentId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; assignmentId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// check if student assignment exists&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; studentAssignment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; prisma&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;studentAssignment
	    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findUnique&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	      where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	        studentId_assignmentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	          assignmentId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	          studentId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;studentAssignment&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;404&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Errors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AssignmentNotFound&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        success&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;studentAssignment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;submitted&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Errors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AssignmentAlreadySubmitted&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        success&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; studentAssignmentUpdated &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; prisma
	    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;studentAssignment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	      where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	        studentId_assignmentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	          assignmentId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	          studentId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	      data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	        status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;submitted&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;201&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseForResponse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;studentAssignmentUpdated&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      success&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    res
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
	      error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Errors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ServerError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
	      data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
	      success&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; 
	    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Aside from the barebones design, there’s a lot of logic here.&lt;/p&gt;
&lt;p&gt;Some application logic. Some business logic. Some validation, some errors &amp;#x26; exceptions.&lt;/p&gt;
&lt;p&gt;Lots going on here, and lots of room for things to go wrong. And they will, and without tests, it’s going to feel pretty painful to keep your code in check over time without a lot of manual testing.&lt;/p&gt;
&lt;p&gt;Let’s not go that road.&lt;/p&gt;
&lt;h2 id=&quot;Creating-a-test-rig&quot; style=&quot;position:relative;&quot;&gt;Creating a test rig&lt;a href=&quot;#Creating-a-test-rig&quot; aria-label=&quot;Creating a test rig permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you’re new to high value acceptance testing, know that there are 3 types of excellent tests we can write which will give you a MASSIVE amount of confidence in your code, if done correctly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;high value e2e&lt;/li&gt;
&lt;li&gt;high value unit&lt;/li&gt;
&lt;li&gt;high value integration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But to write any of these, you’ll first need to set up a test rig.&lt;/p&gt;
&lt;p&gt;What is a test rig? &lt;/p&gt;
&lt;p&gt;I love this concept.&lt;/p&gt;
&lt;p&gt;Admittedly, if you’re only used to writing a few Jest unit tests here and there, this might feel a bit odd to you.&lt;/p&gt;
&lt;p&gt;But a test rig is a specific architectural component you create which is responsible for running your high value tests against either your frontend, backend, or both.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/legacy-code/4-tier-acceptance-test-rig.png&quot; alt=&quot;4 Tiers Acceptance Test Rig&quot;&gt;

Comprised of 4 layers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;acceptance test specification layer&lt;/li&gt;
&lt;li&gt;executable specification layer&lt;/li&gt;
&lt;li&gt;domain specific language layer&lt;/li&gt;
&lt;li&gt;protocol driver layer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;... this is the first thing I teach to developers in the &lt;a href=&quot;https://www.essentialist.dev/the-software-essentialist&quot;&gt;Best Practice-First phase of craftship&lt;/a&gt; once they’re past the basics of testing and they’re ready to get serious.&lt;/p&gt;
&lt;p&gt;It’s a little bit different on the frontend vs. the backend, but those 4 layers are always present.&lt;/p&gt;
&lt;h2 id=&quot;From-user-stories-to-high-value-e2e-acceptance-test&quot; style=&quot;position:relative;&quot;&gt;From user stories to high value e2e acceptance test&lt;a href=&quot;#From-user-stories-to-high-value-e2e-acceptance-test&quot; aria-label=&quot;From user stories to high value e2e acceptance test permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Using-high-value-e2e-tests&quot; style=&quot;position:relative;&quot;&gt;Using high value e2e tests&lt;a href=&quot;#Using-high-value-e2e-tests&quot; aria-label=&quot;Using high value e2e tests permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once we set up this 4 tier architecture, we’ll be ready to start characterizing our code.&lt;/p&gt;
&lt;p&gt;Now, I recommend for most scenarios, to use high value e2e or high value integration tests to test your features.&lt;/p&gt;
&lt;p&gt;If you’re characterizing a backend, there’s little value in choosing integration over e2e.&lt;/p&gt;
&lt;p&gt;If you’re characterizing a frontend, high value integration tests can be extremely powerful, but for you to do that, you need to know how to decouple from React/the view layer (but that’s another email).&lt;/p&gt;
&lt;h3 id=&quot;The-user-story&quot; style=&quot;position:relative;&quot;&gt;The user story&lt;a href=&quot;#The-user-story&quot; aria-label=&quot;The user story permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We’ll do one for now, but imagine you had a ton of features you wanted to make sure work safely first before you change anything.&lt;/p&gt;
&lt;p&gt;You’d start by gathering up those user stories.&lt;/p&gt;
&lt;p&gt;You can write &apos;em rough. Here&apos;s what I gather from this code.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;gherkin&quot;&gt;&lt;pre class=&quot;language-gherkin&quot;&gt;&lt;code class=&quot;language-gherkin&quot;&gt;As a student
    &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; want to submit an assignment
    So that I can get a grade&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Dope.&lt;/p&gt;
&lt;p&gt;What’s next? The test.&lt;/p&gt;
&lt;h3 id=&quot;Writing-the-acceptance-test&quot; style=&quot;position:relative;&quot;&gt;Writing the acceptance test&lt;a href=&quot;#Writing-the-acceptance-test&quot; aria-label=&quot;Writing the acceptance test permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I’m a huge fan of Gherkin, a way to express your functional using Given-When-Then in a super human-readable way.&lt;/p&gt;
&lt;p&gt;Gherkin is great, and it’s pretty much a BDD staple for testing.&lt;/p&gt;
&lt;p&gt;To continue, I’d express that story as a Feature using jest-cucumber, document the success case, and then document the many edge cases I think I’m noticing as well. I’ll just do one for now. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;gherkin&quot;&gt;&lt;pre class=&quot;language-gherkin&quot;&gt;&lt;code class=&quot;language-gherkin&quot;&gt;&lt;span class=&quot;token feature&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Feature:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Submit an assignment&lt;/span&gt;

    As a student
    I want to submit an assignment
    So that I can get a grade

&lt;/span&gt;    &lt;span class=&quot;token scenario&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Scenario:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Successfully submit an assignment&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token atrule&quot;&gt;Given&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; was assigned to an assignment
        &lt;span class=&quot;token atrule&quot;&gt;When&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; submit the assignment
        &lt;span class=&quot;token atrule&quot;&gt;Then&lt;/span&gt; It should be marked as submitted

    &lt;span class=&quot;token scenario&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Scenario:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Fail to submit an assignment twice&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token atrule&quot;&gt;And&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; submitted the assignment
        &lt;span class=&quot;token atrule&quot;&gt;When&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; submit the assignment again
        &lt;span class=&quot;token atrule&quot;&gt;Then&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; should see an error message&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Writing-the-executable-specification&quot; style=&quot;position:relative;&quot;&gt;Writing the executable specification&lt;a href=&quot;#Writing-the-executable-specification&quot; aria-label=&quot;Writing the executable specification permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Then comes the executable specification — the actual test file itself.&lt;/p&gt;
&lt;p&gt;Most of us are somewhat familiar with these, although maybe not using the Gherkin/acceptance test specification strategy. Here’s what that test could look like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; feature &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loadFeature&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../features/submitAssignment.feature&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;defineFeature&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;feature&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;afterEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;resetDatabase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Successfully submit an assignment&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
	  given&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; when&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; then 
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; requestBody&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; response&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; studentAssignment&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; StudentAssignment&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;given&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;I was assigned to an assignment&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      studentAssignment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; studentAssignment
	      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromStudent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;studentBuilder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;andAssignment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;assignmentBuilder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;I submit the assignment&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      requestBody &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        studentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; studentAssignment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;student&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        assignmentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; studentAssignment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;assignment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/student-assignments/submit&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;requestBody&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;It should be marked as submitted&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;201&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;submitted&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;The-domain-specific-language&quot; style=&quot;position:relative;&quot;&gt;The domain specific language&lt;a href=&quot;#The-domain-specific-language&quot; aria-label=&quot;The domain specific language permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Notice the language that I use to set up the test:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;studentAssignment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; studentAssignment
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromStudent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;studentBuilder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;andAssignment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;assignmentBuilder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This stuff.&lt;/p&gt;
&lt;p&gt;Ah, the wonderful Builder Pattern. I’ll explain more in a coming email later this week, but I love these. &lt;/p&gt;
&lt;p&gt;Extremely powerful. Extremely declarative. Extremely versatile pattern.&lt;/p&gt;
&lt;h2 id=&quot;The-protocol-driver&quot; style=&quot;position:relative;&quot;&gt;The protocol driver&lt;a href=&quot;#The-protocol-driver&quot; aria-label=&quot;The protocol driver permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The protocol driver is what actually crosses the threshold, taking us from one system (our test rig) to the actual system itself (the backend, in this case).&lt;/p&gt;
&lt;p&gt;I opted to use supertest here, but sometimes I’ll actually build my own apiClient for many, many reasons which I’ll also get to another time.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token function&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;I submit the assignment&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  requestBody &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    studentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; student&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    assignmentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; assignment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/student-assignments/submit&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;requestBody&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;How-to-continue&quot; style=&quot;position:relative;&quot;&gt;How to continue?&lt;a href=&quot;#How-to-continue&quot; aria-label=&quot;How to continue permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you characterize your features first using the 4-tier acceptance test rig, you’ll be in great shape.&lt;/p&gt;
&lt;p&gt;That’s the main idea.&lt;/p&gt;
&lt;p&gt;I recommend spending some time getting this blanket of tests down first before you make any invasive changes/refactorings, because honestly — you could have some bleed-over between your Vertical Slices (your API calls).&lt;/p&gt;
&lt;p&gt;While I could go on, this email is already pretty long.&lt;/p&gt;
&lt;p&gt;I&apos;ll wrap it here for now.&lt;/p&gt;
&lt;p&gt;Enjoy the rest of your week ~&lt;/p&gt;
&lt;p&gt;As always,
To Mastery&lt;/p&gt;
&lt;p&gt;Khalil&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.essentialist.dev/the-software-essentialist&quot;&gt;PS: You can join The Software Essentialist for an additional 15% off before we ship the Pattern-First phase of craftship. Use the code TESTING-MASTERY before August 19th to join us in the course &amp;#x26; community&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[The Metaphysical Mental Models: Abstraction & The Feedback Loop]]></title><description><![CDATA[Recently, I've been thinking about those early days of when I first started out coding. There were a bajillion things to learn, right? And…]]></description><link>https://khalilstemmler.com/articles/abstraction-the-feedback-loop-mental-models/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/abstraction-the-feedback-loop-mental-models/</guid><pubDate>Tue, 26 Mar 2024 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Recently, I&apos;ve been thinking about those early days of when I first started out coding.&lt;/p&gt;
&lt;p&gt;There were a bajillion things to learn, right?&lt;/p&gt;
&lt;p&gt;And today, we have new tools, libraries, frameworks… and AI tech. &lt;/p&gt;
&lt;p&gt;I remember that feeling. Like I was on a never-ending treadmill, always learning new stuff, but still writing spaghetti messes and untestable code in my codebases.&lt;/p&gt;
&lt;p&gt;Eventually I had enough of that and went on a journey to discover how to master what matters.&lt;/p&gt;
&lt;p&gt;Today, after all that time and what I&apos;ve seen, I realize something key – simplicity is golden.&lt;/p&gt;
&lt;p&gt;And that goes for most things in life actually.&lt;/p&gt;
&lt;p&gt;But if I were to write a letter to myself when I was first starting out, I’d tell him this:&lt;/p&gt;
&lt;p&gt;“Khalil. Keep it simple. Your entire job as a programmer is to perform problem decomposition. Break valuable problems down into bite-sized pieces and find solutions with code.&quot;&lt;/p&gt;
&lt;p&gt;I’d also tell him that:&lt;/p&gt;
&lt;p&gt;“Programming and problem decomposition are mostly about mental models. Your code is only as good as if it solves a problem or not, and if it uses language and symbols that other developers understand. To help you, there are 2 main mental models you need to master: Abstraction and The Feedback Loop. Keep learning new tools and improving your stack, yes, but primarily focus on how to use these concepts while coding. Everything will come into place if you do.” &lt;/p&gt;
&lt;p&gt;Allow me to explain what they are.
&lt;/p&gt;
&lt;h2 id=&quot;Abstraction&quot; style=&quot;position:relative;&quot;&gt;Abstraction&lt;a href=&quot;#Abstraction&quot; aria-label=&quot;Abstraction permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/mental-models/abstraction.png&quot; alt=&quot;abstraction&quot;&gt;

How aware are you of what’s going on behind the scenes when you press “POWER” on your tv remote? Do you know how the sequences of 0’s and 1’s sent from the remote to the receiver are encoded, transmitted &amp;#x26; decoded?&lt;/p&gt;
&lt;p&gt;Or is it simply enough to think “power button means the tv turns on”?&lt;/p&gt;
&lt;p&gt;Second answer, right? Yeah, second answer.&lt;/p&gt;
&lt;p&gt;Abstraction is one of the least understood concepts… but also the most important.&lt;/p&gt;
&lt;p&gt;It’s all about taking a big, complex problem, breaking it apart and creating new, easier to understand chunks or layers of the problem that interact with each other to solve the problem.&lt;/p&gt;
&lt;p&gt;Do it right and our codebases are valuable, readable, understandable — glorious.&lt;/p&gt;
&lt;p&gt;Do it incorrectly and our code starts to look like the inside of a turtle (I have no idea what that might look like, nor do I want to, but I imagine it’s not pleasant).&lt;/p&gt;
&lt;h2 id=&quot;The-Feedback-Loop&quot; style=&quot;position:relative;&quot;&gt;The Feedback Loop&lt;a href=&quot;#The-Feedback-Loop&quot; aria-label=&quot;The Feedback Loop permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/mental-models/the-feedback-loop.png&quot; alt=&quot;the feedback loop&quot;&gt;

I used to spend so much time changing lines of React code, refreshing the UI, re-walking through a set of steps to see if it worked and - nope, didn&apos;t work, time to try again.&lt;/p&gt;
&lt;p&gt;These days I just write a test, the minimum amount of code I have to, and avoid all of that.&lt;/p&gt;
&lt;p&gt;If I could get those hours back. &lt;/p&gt;
&lt;p&gt;I&apos;d probably have had so many more hours to go pro Junkrat in my Overwatch career back then.&lt;/p&gt;
&lt;p&gt;There are so many more effective ways to work. In the course, we talk about something called The Ideal Developer Workflow and FA²STR but really, simplicity-wise - it comes down to introducing Feedback Loops.&lt;/p&gt;
&lt;p&gt;For example, when we learn how to talk to customers, use things like Impact Maps, DDD techniques like Event Storming &amp;#x26; Modelling to clarify before we build, and when we work outside-in by driving your code with tests first (yes, tests, y&apos;all - I know... trust me though, they&apos;re not as scary as they seem)… well, then we’re using feedback loops conceptually.&lt;/p&gt;
&lt;p&gt;How so?&lt;/p&gt;
&lt;p&gt;We’re making a guess, taking action based on that guess, and then we check to make sure we’re OK before continuing deeper and deeper into abstraction-land.&lt;/p&gt;
&lt;p&gt;Do this right and we build the right thing, the right way, and with useful tests that’ve got our backs (to protect against accidentally changing some code that breaks an existing feature).&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;So next time you&apos;re coding, if you care about long-term quality (you probably do if you&apos;re subscribed to this newsletter - you absolute class act), think about abstraction &amp;#x26; the feedback loop.&lt;/p&gt;
&lt;p&gt;How might you use these ideas better?&lt;/p&gt;
&lt;p&gt;Framing your focus this way makes a huge difference.&lt;/p&gt;
&lt;p&gt;And hey, nobody gets it perfect from the start.&lt;/p&gt;
&lt;p&gt;Actually, I’ve learned that there are about &lt;a href=&quot;https://www.essentialist.dev/offers/hN4GMJcp&quot;&gt;5 Stages of Phases of Craftship&lt;/a&gt; (a coaching tool I use to make sense of a developer&apos;s skill level) that we tend to go through as we improve.&lt;/p&gt;
&lt;p&gt;This happens naturally if we&apos;re exposed to the right paradigm shifts at the right times, where each one involves better use of each of the essential mental models!&lt;/p&gt;
&lt;p&gt;But more on that later.&lt;/p&gt;
&lt;p&gt;Looking forward to hearing your thoughts on this.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Why You Have Spaghetti Code]]></title><description><![CDATA[Before we begin: Doors open for the latest version of The Software Essentialist on March 31st. Join the waitlist for perks, bonuses & 5…]]></description><link>https://khalilstemmler.com/articles/divergence-convergence-spaghetti-code/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/divergence-convergence-spaghetti-code/</guid><pubDate>Sun, 24 Mar 2024 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Before we begin: Doors open for the latest version of The Software Essentialist on March 31st. &lt;a href=&quot;https://www.essentialist.dev/master-the-essentials-of-software-design-with-typescript&quot;&gt;Join the waitlist for perks, bonuses &amp;#x26; 55% off&lt;/a&gt;.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If I had to call out the definitive Code-First experience, it&apos;s that feeling when you realize you&apos;re writing code that gets &lt;strong&gt;worse&lt;/strong&gt; instead of better all the time.
Code where no one understands it, no one wants to touch it because they&apos;re afraid they&apos;ll break something...&lt;/p&gt;
&lt;p&gt;And as a result, you get this pretty unfulfilling working your codebase.&lt;/p&gt;
&lt;p&gt;It feels disheartening knowing that you tried your best, yet still: spaghetti.&lt;/p&gt;
&lt;p&gt;Been there.&lt;/p&gt;
&lt;p&gt;I talk about this in the Phases of Craftship - that Code-First developers need to go through this experience at least once (or twice) to realize that &lt;em&gt;code isn&apos;t enough&lt;/em&gt;. Only then when you experience this do you typically realize it&apos;s time to look for better practices.&lt;/p&gt;
&lt;p&gt;But why does this happen in the first place?&lt;/p&gt;
&lt;p&gt;What&apos;s at the heart of this &lt;strong&gt;un-maintainability&lt;/strong&gt; problem?&lt;/p&gt;
&lt;p&gt;I believe the answer lies in the ideas of &lt;em&gt;divergence&lt;/em&gt; and &lt;em&gt;convergence&lt;/em&gt;, two fundamental laws of abstraction and creation (of anything).&lt;/p&gt;
&lt;h2 id=&quot;Divergence--convergence&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Divergence &amp;#x26; convergence&lt;/strong&gt;&lt;a href=&quot;#Divergence--convergence&quot; aria-label=&quot;Divergence  convergence permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To create anything in the world relies upon these two creative forces: &lt;em&gt;divergence&lt;/em&gt; and &lt;em&gt;convergence&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/divergence-convergence.png&quot; alt=&quot;Divergence &amp;#x26; Convergence&quot;&gt;&lt;/p&gt;
&lt;p&gt;Divergence is about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;expansion&lt;/li&gt;
&lt;li&gt;emergence&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Where convergence is about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;contraction&lt;/li&gt;
&lt;li&gt;contracts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For well-designed creative works, we&apos;re going to need to use a mixture of these two sorts of forces: &lt;strong&gt;these two&lt;/strong&gt; &lt;strong&gt;forms of design (upfront design &amp;#x26; emergent design)&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Divergence-involves-making-a-mess&quot; style=&quot;position:relative;&quot;&gt;Divergence involves making a mess&lt;a href=&quot;#Divergence-involves-making-a-mess&quot; aria-label=&quot;Divergence involves making a mess permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For example, when I&apos;m in the initial brainstorming phase of writing newsletters and course modules, I fully expect a mess. You&apos;ll see messy whiteboards, papers, voice notes - all sorts of things. I don&apos;t give too much focus to anything other than getting the ideas out &amp;#x26; following the trains of thought.&lt;/p&gt;
&lt;p&gt;Or when I sit down to write a song. Sometimes I&apos;ll beatbox the drums, make noise, add parts randomly, use whatever I have available, or &lt;em&gt;ramble&lt;/em&gt; the lyrics. I don&apos;t give too much focus to anything other that following what&apos;s interesting to me.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;This is all an act of divergence. It&apos;s un-boundaried, flowing, and it can basically go forever (if you let it)&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Divergence is a crucial part of any creative process, but any time we write code without boundaries, this is where the spaghetti comes from.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Well, not where REAL spaghetti comes from 🍝 - that&apos;s from Italy, but you know what I mean).&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;Convergence-involves-using-boundaries&quot; style=&quot;position:relative;&quot;&gt;Convergence involves using boundaries&lt;a href=&quot;#Convergence-involves-using-boundaries&quot; aria-label=&quot;Convergence involves using boundaries permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If divergence is all about expanding and building up, the convergence is all about bringing things to a completion.&lt;/p&gt;
&lt;p&gt;In the writing process, this is where I look at the brainstorm and select the goals, write the headers &amp;#x26; the summary before writing the content.&lt;/p&gt;
&lt;p&gt;In the music production process, this is where I&apos;d select the instrumentation, take it to the studio and get notes from the producer before re-recording it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Convergence is all about starting from the end. It&apos;s all about defining exactly what success will look like, before we even start, and then every action we take next is to bring the work to a close.&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;It&apos;s a focus on &lt;strong&gt;outcomes&lt;/strong&gt;, not &lt;strong&gt;steps&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;And it&apos;s something we &lt;strong&gt;contractualize&lt;/strong&gt; -- typically, in programming using acceptance tests, like so:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/divergence-convergence/acceptance-test.png&quot; alt=&quot;Acceptance Test&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;You-need-both&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;You need both&lt;/strong&gt;&lt;a href=&quot;#You-need-both&quot; aria-label=&quot;You need both permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Acceptance tests are contracts that help us &lt;strong&gt;converge&lt;/strong&gt;. They give us the absolute bare minimum set of things our code has to do.&lt;/p&gt;
&lt;p&gt;And when we configure an &lt;strong&gt;acceptance testing rig&lt;/strong&gt;, we can actually balance a mixture of test-code-test-code-test-code moving inwards into the codebase, writing as minimal code as possible.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/divergence-convergence/test-code.png&quot; alt=&quot;Zig Zag Test-Code&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;Play-the-zig-zag&quot; style=&quot;position:relative;&quot;&gt;Play the zig-zag&lt;a href=&quot;#Play-the-zig-zag&quot; aria-label=&quot;Play the zig zag permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It&apos;s incredible. Every creative process involves this zig zag between the two.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Writing a newsletter&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Brainstorm (divergence)&lt;/li&gt;
&lt;li&gt;Select goals (convergence)&lt;/li&gt;
&lt;li&gt;Write summary (divergence)&lt;/li&gt;
&lt;li&gt;Write the headers (convergence)&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Making a song&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Recording an idea (divergence)&lt;/li&gt;
&lt;li&gt;Selecting the arrangement (convergence)&lt;/li&gt;
&lt;li&gt;Recording the demo (divergence)&lt;/li&gt;
&lt;li&gt;Producer helps suggest revisions for the next recording (convergence)&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;FAQ&quot; style=&quot;position:relative;&quot;&gt;FAQ&lt;a href=&quot;#FAQ&quot; aria-label=&quot;FAQ permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;What-about-refactoring&quot; style=&quot;position:relative;&quot;&gt;What about refactoring?&lt;a href=&quot;#What-about-refactoring&quot; aria-label=&quot;What about refactoring permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Refactoring is a form of convergence. You&apos;re cutting down on what was divergently created.&lt;/p&gt;
&lt;p&gt;But consider the problem with refactoring after having performed &lt;strong&gt;way too many divergence cycles in a row&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;It&apos;s like asking a painter to completely change a painting to a new one.&lt;/p&gt;
&lt;p&gt;At that point, it&apos;d just be way easier to create a new painting.&lt;/p&gt;
&lt;p&gt;And this is &lt;strong&gt;precisely&lt;/strong&gt; what Code-First developers often feel called to do.&lt;/p&gt;
&lt;p&gt;Ah yes, The Classic Rewrite™️.&lt;/p&gt;
&lt;p&gt;The costly and expensive rewrites.&lt;/p&gt;
&lt;p&gt;Better solution is to avoid this altogether, start with valuable tests and zig-zag your features to fruition.&lt;/p&gt;
&lt;h3 id=&quot;How-can-I-fix-my-spaghetti-code&quot; style=&quot;position:relative;&quot;&gt;How can I fix my spaghetti code?&lt;a href=&quot;#How-can-I-fix-my-spaghetti-code&quot; aria-label=&quot;How can I fix my spaghetti code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;OK, so what to do if you&apos;re facing spaghetti &lt;strong&gt;right now&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Eat it. 🍝 Spaghetti is delicious. Ha, kidding.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For real though, in this situation, the experts suggest you focus on SAFELY refactoring your code.&lt;/p&gt;
&lt;p&gt;And the first step to SAFELY refactor your code is to &lt;em&gt;characterize&lt;/em&gt; it.&lt;/p&gt;
&lt;p&gt;What do I mean by this?&lt;/p&gt;
&lt;p&gt;Functionally, a characterization test is the same thing as an acceptance test; meaning: it documents the feature and the acceptance criteria, but from a high level. &lt;/p&gt;
&lt;p&gt;So &lt;em&gt;after&lt;/em&gt; you&apos;ve already made a mess (or you&apos;re getting ready to clean up some legacy code), start with &lt;strong&gt;convergence&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Write a &lt;em&gt;characterization test&lt;/em&gt; before you do anything else.&lt;/p&gt;
&lt;p&gt;Just like how a tailor sets pins in place before cutting any fabric, you want to clarify the &lt;strong&gt;Vertical Slice&lt;/strong&gt; of functionality - the feature that you&apos;re about to adjust - and you want to do this before you do anything else.&lt;/p&gt;
&lt;p&gt;This can vary in terms of challenge and complexity.&lt;/p&gt;
&lt;p&gt;For example, your features are all coupled together, you might have to characterize &apos;em all upfront, otherwise you could break one by fixing another.&lt;/p&gt;
&lt;p&gt;I know developers &lt;em&gt;love&lt;/em&gt; the phrase &quot;it depends&quot;. &lt;em&gt;That&apos;s sarcasm.&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;But really, it &lt;em&gt;does&lt;/em&gt; depend. &lt;/p&gt;
&lt;p&gt;It depends primarily on how &lt;a href=&quot;https://khalilstemmler.com/wiki/coupling-cohesion-connascence/&quot;&gt;coupled&lt;/a&gt; your features are to each other AND how easy it is to work &lt;em&gt;with&lt;/em&gt; or &lt;em&gt;mock out&lt;/em&gt; any connected infrastructure to &lt;em&gt;test infrastructure&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I&apos;ll share more on this in future letters.&lt;/p&gt;
&lt;h2 id=&quot;In-summary&quot; style=&quot;position:relative;&quot;&gt;In summary&lt;a href=&quot;#In-summary&quot; aria-label=&quot;In summary permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What&apos;s the main takeaway of all this?&lt;/p&gt;
&lt;p&gt;When you write a test, you&apos;re converging.&lt;/p&gt;
&lt;p&gt;When you write code, you&apos;re diverging.&lt;/p&gt;
&lt;p&gt;When you only write code, it&apos;ll continue to diverge and diverge until it&apos;s extremely hard to continue to stack new features and functionality on top.&lt;/p&gt;
&lt;p&gt;The solution is to play the zig-zag of divergence and convergence. Cutting and adding.&lt;/p&gt;
&lt;p&gt;And finally, when you &lt;strong&gt;&lt;em&gt;start&lt;/em&gt; with a valuable test&lt;/strong&gt;, you actually set up a vector of success. You get a guardrail which helps you avoid &lt;strong&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/software-professionalism/absolute-and-relative-complexity/&quot;&gt;accidental complexity&lt;/a&gt;&lt;/strong&gt;, and helps you converge &lt;em&gt;only&lt;/em&gt; on what matters. On what&apos;s valuable.&lt;/p&gt;
&lt;p&gt;So learn to do &apos;em both. Convergence &amp;#x26; divergence. Tests &amp;#x26; production code. &lt;/p&gt;
&lt;p&gt;This is how we get out of Code-First spaghetti territory.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;That&apos;s all for this letter, folks.&lt;/p&gt;
&lt;p&gt;Enjoy the rest of your weekend.&lt;/p&gt;
&lt;p&gt;As always,
To Mastery&lt;/p&gt;
&lt;p&gt;Khalil&lt;/p&gt;
&lt;p&gt;&lt;em&gt;PS: A reminder that the waitlist for TWSE 55% opens March 31st at 8:00AM EST. We&apos;ve already reached 300 waitlist submissions with only 200 spots. &lt;a href=&quot;https://www.essentialist.dev/master-the-essentials-of-software-design-with-typescript&quot;&gt;Get notified early when doors open here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Reality → Perception → Definition → Action (Why Language Is Vital As a Developer)]]></title><description><![CDATA[It was only a matter of time before I fell in love with Domain-Driven Design. Not only did it clarify how to organize my code and untangle…]]></description><link>https://khalilstemmler.com/articles/definition-creates-reality/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/definition-creates-reality/</guid><pubDate>Wed, 10 Jan 2024 04:05:26 GMT</pubDate><content:encoded>&lt;p&gt;It was only a matter of time before I fell in love with Domain-Driven Design.&lt;/p&gt;
&lt;p&gt;Not only did it clarify how to organize my code and untangle the spaghetti…&lt;/p&gt;
&lt;p&gt;The truth is: &lt;em&gt;I’m a word nerd.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I’ve always loved books. &lt;/p&gt;
&lt;p&gt;I’ve always loved writing. &lt;/p&gt;
&lt;p&gt;I’ve always found magic in accents, languages, blogging, poetry, songwriting, copywriting..&lt;/p&gt;
&lt;p&gt;Anything and everything within the realm of words, I’m in.&lt;/p&gt;
&lt;p&gt;While I’d love to “TED talk” your inbox full of word-related self development content like affirmations, NLP, subconscious programming &amp;#x26; so on… &lt;/p&gt;
&lt;p&gt;I ain&apos;t Tony Robbins.&lt;/p&gt;
&lt;p&gt;If you’re getting this email, it’s because you’re a software developer.&lt;/p&gt;
&lt;p&gt;So let&apos;s focus in.&lt;/p&gt;
&lt;h2 id=&quot;What-well-cover&quot; style=&quot;position:relative;&quot;&gt;What we&apos;ll cover&lt;a href=&quot;#What-well-cover&quot; aria-label=&quot;What well cover permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this letter, I’d like to take you on a little journey and:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;discuss why language matters so much as a developer&lt;/li&gt;
&lt;li&gt;explain how I’ve noticed code-first developers think &amp;#x26; talk about code&lt;/li&gt;
&lt;li&gt;discuss how refining my language and definitions has helped me improve my ability to develop &lt;em&gt;The Software Essentialist&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;share an update on the course &amp;#x26; book progress&lt;/li&gt;
&lt;li&gt;let you know about an upcoming sale for new course members&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Why-language-matters-as-a-developer&quot; style=&quot;position:relative;&quot;&gt;Why language matters as a developer&lt;a href=&quot;#Why-language-matters-as-a-developer&quot; aria-label=&quot;Why language matters as a developer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Say I told you to go look for stones and bring ‘em back.&lt;/p&gt;
&lt;p&gt;Why? Ah, because we’re going to cast ‘em in the water and make pretty ripples. &lt;/p&gt;
&lt;p&gt;Nice way to spend a Sunday afternoon, no?&lt;/p&gt;
&lt;p&gt;Cool, so &lt;em&gt;unconsciously&lt;/em&gt; what’d you’d do is formulate a &lt;strong&gt;definition for &lt;em&gt;rounded&lt;/em&gt;, &lt;em&gt;cast-able stones&lt;/em&gt; in your mind&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;In neuroscience, there’s something called the &lt;strong&gt;&lt;em&gt;Reticular Activating System&lt;/em&gt;&lt;/strong&gt; — basically the part of your brain that helps you notice stuff that’s relevant.&lt;/p&gt;
&lt;p&gt;Based on this instruction, you’d constrain your perception to small, tiny, throwable stones, probably.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Now if I said that we were going to get some stones again, but this time, it was to forge some weapons.&lt;/p&gt;
&lt;p&gt;Why? &lt;/p&gt;
&lt;p&gt;Because we’re gonna head into the woods to hunt bears, bring it home &amp;#x26; make a big ol’ bear steak burger.&lt;/p&gt;
&lt;p&gt;You’d probably start looking for a different type of stone. Maybe pointy, jagged, or even larger rocks to be quite honest, right?&lt;/p&gt;
&lt;p&gt;Basically, what I’m trying to convey to you is that your &lt;em&gt;definitions&lt;/em&gt; (conscious or unconscious) affects your perception.&lt;/p&gt;
&lt;p&gt;And &lt;strong&gt;the way you &lt;em&gt;think&lt;/em&gt; and &lt;em&gt;talk&lt;/em&gt; about about code affects how you &lt;em&gt;write&lt;/em&gt; code&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This is crucial. &lt;/p&gt;
&lt;p&gt;It’s the way I make sense of how most developers move through the &lt;em&gt;Phases of Craftship&lt;/em&gt; (ie: this is what I call the 5 stages of software development mastery).&lt;/p&gt;
&lt;h2 id=&quot;Code-First-developers-think-in-terms-of-tools-and-libraries&quot; style=&quot;position:relative;&quot;&gt;Code-First developers think in terms of tools and libraries&lt;a href=&quot;#Code-First-developers-think-in-terms-of-tools-and-libraries&quot; aria-label=&quot;Code First developers think in terms of tools and libraries permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At the end of the day, your job as as developer is one single thing: problem decomposition&lt;/p&gt;
&lt;p&gt;It’s how well you go from problem to solution.&lt;/p&gt;
&lt;p&gt;And developers who are just getting started or experiencing a lot of friction in the way that they work? I call these &lt;a href=&quot;/articles/the-phases-of-craftship/code-first/&quot;&gt;Code-First developers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is the first phase of craftship.&lt;/p&gt;
&lt;p&gt;Code-First developers think about code in terms of libraries, tools, “frontend” and “backend”.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/definition-creates-reality/code-first.png&quot; alt=&quot;Code-First Development&quot;&gt;&lt;/p&gt;
&lt;p&gt;Because this isn’t a very &lt;em&gt;nuanced&lt;/em&gt; approach to problem decomposition, generally, the quality isn’t great. And when we’re at this phase, we run into basically &lt;em&gt;all the problems&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Spaghetti code, fighting the framework, unknown unknowns, refreshing and changing a line of code over and over, debuggers all over the place.&lt;/p&gt;
&lt;p&gt;Been there.&lt;/p&gt;
&lt;p&gt;Totally normal. &lt;/p&gt;
&lt;p&gt;Painful, but necessary when you’re first starting out.&lt;/p&gt;
&lt;p&gt;Compared to later stages like the **Responsibility-First Phase of Craftship, your definitions of code — the way you think about it — it’s more within the domain of roles, responsibilities, collaborations and &lt;a href=&quot;/articles/object-oriented/design/object-stereotypes/&quot;&gt;stereotypical objects&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can kinda see into the matrix a bit here because you’re looking at code from a much deeper, much more refined vantage point. It’s almost like taking a magnifying glass to a codebase. You see all the little itty-bitty atomic aspects of it that make it work.&lt;/p&gt;
&lt;p&gt;From this perspective, you have way more options, control, and mastery over the way you work.&lt;/p&gt;
&lt;p&gt;You can zoom all the way out and look at problems from a code-first “blocky” api + database + frontend perspective…&lt;/p&gt;
&lt;p&gt;And you can zoom all the way in and look at problems and say things like: &lt;em&gt;“ah, this library (like Redux) carries out the &lt;a href=&quot;https://khalilstemmler.com/articles/object-oriented/design/object-stereotypes/#4-The-Coordinator&quot;&gt;coordinator object stereotype&lt;/a&gt; responsibilities, and that stereotypically behaves this way and talks to these other stereotypical objects this way”.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;At this level, you can identify patterns, tie abstractions together, design custom abstractions at an object-oriented level, and make much better decisions for how to select libraries and frameworks (to name a few).&lt;/p&gt;
&lt;p&gt;Ultimately, when you can think deeper - you can decompose problems in more strategic, formless ways that the situation calls for.&lt;/p&gt;
&lt;p&gt;Does that make sense? When your language is more refined, your problem-solving capabilities are more refined.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(But that’s obvious, right?)&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;How-I-used-Domain-Driven-Design-principles-to-refine-my-course-development-philosophy&quot; style=&quot;position:relative;&quot;&gt;How I used Domain-Driven Design principles to refine my course development philosophy&lt;a href=&quot;#How-I-used-Domain-Driven-Design-principles-to-refine-my-course-development-philosophy&quot; aria-label=&quot;How I used Domain Driven Design principles to refine my course development philosophy permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A tough pill I had to remember to swallow was that you tend to take a lot of L&apos;s when you start a new business.&lt;/p&gt;
&lt;p&gt;It&apos;s just the way it goes.&lt;/p&gt;
&lt;img src=&quot;https://www.ambrosegrowth.com/wp-content/uploads/2023/02/1548885950848.png&quot;&gt;
&lt;p class=&quot;caption&quot;&gt;See: Ray Dalio&apos;s framework for doing anything difficult&lt;/p&gt;
&lt;p&gt;Personally, I had to undergo a period of looking at my own definitions because honestly…&lt;/p&gt;
&lt;p&gt;On a positive note: after launching the early adopter version of &lt;a href=&quot;https://essentialist.dev&quot;&gt;The Software Essentialist&lt;/a&gt; not only was last year the most fulfilling, growth-oriented, and illuminating year of my life…&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Some students got jobs at well-known companies, others had major aha moments that personally took me years to grasp)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;... but on a more realistic note: it was also the most &lt;strong&gt;difficult&lt;/strong&gt; and &lt;em&gt;challenging&lt;/em&gt; one I’ve faced yet as well.&lt;/p&gt;
&lt;p&gt;Outside of the personal development growing pains of running a new company, I faced a number of course development challenges and drawbacks like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;doing a lot of re-work&lt;/li&gt;
&lt;li&gt;big chunks of the curriculum had to get re-designed&lt;/li&gt;
&lt;li&gt;video &amp;#x26; audio editing snags&lt;/li&gt;
&lt;li&gt;being “forced” to work 10-15+ hour days&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, as a first time course creator, in a new domain of mastery, I realized much later on, that I was basically the equivalent of a Code-First developer as a course creator.&lt;/p&gt;
&lt;p&gt;Entirely new things to learn. Tons of mistakes around every corner.&lt;/p&gt;
&lt;p&gt;Alex Hormozi calls this “paying your tuition to the market”.&lt;/p&gt;
&lt;p&gt;Fair enough.&lt;/p&gt;
&lt;p&gt;But in December 2023, after a year of Q&amp;#x26;As, videos, learning new skills &amp;#x26; publishing content, took my foot off the gas for a while to question my definitions. &lt;/p&gt;
&lt;p&gt;To analyze the way I think and work.&lt;/p&gt;
&lt;p&gt;Basically, here’s what I did:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I collected all my learnings over the year&lt;/li&gt;
&lt;li&gt;I asked myself every question I could ask myself about how I work, manage time, structure content, and structure my work&lt;/li&gt;
&lt;li&gt;I answered those questions with what I currently knew to be true&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And with &lt;strong&gt;simple questions and answers&lt;/strong&gt; - this process of diagonis - I watched as my own personal philosophy of course development formulated before my eyes.&lt;/p&gt;
&lt;p&gt;Some of you might just be thinking: “dude, sounds like you’ve just discovered SOPs (standard operating procedures)”.&lt;/p&gt;
&lt;p&gt;Fair enough (x2).&lt;/p&gt;
&lt;p&gt;But upon further reflection, &lt;strong&gt;I realized that this is exactly what we do every time we perform Domain Discovery (one of the 12 Essentials of software design, architecture, testing &amp;#x26; strategy&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/definition-creates-reality/domain-discovery.png&quot; alt=&quot;Untitled&quot;&gt;&lt;/p&gt;
&lt;p&gt;After spending some time condensing down, defining and dividing my concepts into domain language and philosophies…&lt;/p&gt;
&lt;p&gt;Discovering the language of this domain of “&lt;em&gt;Software Essentialist Course Development&lt;/em&gt;”…&lt;/p&gt;
&lt;p&gt;I watched as epiphanies, new initiatives, and a renewed level of clarity for how to produce high-quality material emerged. With a lot less effort.&lt;/p&gt;
&lt;p&gt;For example, I started working with one of our esteemed community members, Lucas, on Interactive Visual Summaries for each of the submodules you walk through in The Phases of Craftship.&lt;/p&gt;
&lt;p&gt;This helps to &lt;strong&gt;untangle the maze&lt;/strong&gt; of topics and present a path for you to learn them in a contextual, practical way.&lt;/p&gt;
&lt;p&gt;He’s built out a v1 of this with d3. &lt;/p&gt;
&lt;p&gt;And I gotta say, it’s pretty incredible so far.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/definition-creates-reality/visual-topic-summary.png&quot; alt=&quot;Visual Topic Summary&quot;&gt;&lt;/p&gt;
&lt;p&gt;And since we’re doing show and tell here… take a look at this.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/definition-creates-reality/course-elements.png&quot; alt=&quot;Course Elements&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is a screencap of some of the the course elements that I’ve invented and named. These are used all throughout the course and as inputs and outputs of the workflows that I use to develop course material.&lt;/p&gt;
&lt;p&gt;It’s amazing how much of this was unconscious, and oftentimes &lt;em&gt;is unconscious&lt;/em&gt;, largely invisible to me, until I sat down and decided to define and divide — to name things &amp;#x26; processes properly.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you haven’t already, take this as a prompt to learn go &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It’s really important for any sort of problem decomposition. Even outside of software development!&lt;/p&gt;
&lt;h2 id=&quot;Whats-next-and-whats-new&quot; style=&quot;position:relative;&quot;&gt;What’s next and what’s new?&lt;a href=&quot;#Whats-next-and-whats-new&quot; aria-label=&quot;Whats next and whats new permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here’s what I’m up to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I’m currently over here in Sydney, Australia happily away from the Toronto weather, doing some leadership training while working on the rest of TSWE.&lt;/li&gt;
&lt;li&gt;Later last year we rolled out a new curriculum based around what I call The Metaphysics and the Phases of Craftship in which there are 5 Phases.&lt;/li&gt;
&lt;li&gt;The Metaphysics is up; I’m in the middle of publishing the refined versions of the first 2 (Code &amp;#x26; Best Practice-First).&lt;/li&gt;
&lt;li&gt;A number of you have asked me to do a Black Friday sale, Christmas Sale and so on — I was pretty hesitant to that idea; I wanted to time things right for y’all to go through this new content. Many of you know I’m using the opportunity to work with you directly as a feedback mechanism to make solidbook.io’s final version the most useful book it possibly can be.&lt;/li&gt;
&lt;li&gt;I’m going to offer a discount for the next 50 new early adopter students to join the program to test out the new Code &amp;#x26; BP-First content &amp;#x26; give feedback. Stay tuned for an update on this.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;-- &lt;/p&gt;
&lt;p&gt;Chat soon, my friends!&lt;/p&gt;
&lt;p&gt;And as always,&lt;/p&gt;
&lt;p&gt;To Mastery&lt;/p&gt;</content:encoded></item><item><title><![CDATA[The Code-First Developer]]></title><description><![CDATA["Wait, is that Sean? Hold on a sec," I exclaimed, interrupting a friend mid-conversation. I had just seen him speeding past the famously…]]></description><link>https://khalilstemmler.com/articles/the-phases-of-craftship/code-first/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/the-phases-of-craftship/code-first/</guid><pubDate>Wed, 10 Jan 2024 04:05:26 GMT</pubDate><content:encoded>&lt;p&gt;&quot;Wait, is that Sean? Hold on a sec,&quot; I exclaimed, interrupting a friend mid-conversation.&lt;/p&gt;
&lt;p&gt;I had just seen him speeding past the famously cursed McDonald&apos;s on the corner of Queen and Spadina in downtown Toronto: Sean, the programmer who had opened my eyes to what great code could look like.&lt;/p&gt;
&lt;p&gt;Walking alongside a fellow &lt;a href=&quot;https://essentialist.dev/&quot;&gt;Software Essentialist Course member&lt;/a&gt;, we strolled past the McDonald&apos;s when I spotted him — this key developer who had played a pivotal role in shaping my career.&lt;/p&gt;
&lt;p&gt;&quot;Whoa, no way... Sean!&quot; I called out, quickening my pace to catch up with him.&lt;/p&gt;
&lt;p&gt;Sure enough, it was him.&lt;/p&gt;
&lt;p&gt;&quot;Oh, hey Khalil, funny running into you down here. How&apos;s it going?&quot; Sean greeted me warmly.&lt;/p&gt;
&lt;p&gt;In that moment, memories flooded back, reminding me of the time we crossed paths in 2017. &lt;/p&gt;
&lt;p&gt;I had been working at a small frontend consultancy, seeking a job that would allow me to focus on my startup, Univjobs, in my spare time without constantly lingering thoughts of work in the evenings.&lt;/p&gt;
&lt;p&gt;I was assigned to collaborate with Sean on a magnetometer software project, exploring the depths of ocean research and exploration.&lt;/p&gt;
&lt;p&gt;Until then, my experience had been marred by messy codebases no one wanted to work with. My first job involved:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Injecting SQL code directly into a massive Java file.&lt;/li&gt;
&lt;li&gt;Totaling over 2000 lines.&lt;/li&gt;
&lt;li&gt;Determining its correctness based on whether it returned any data.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Welcome to the industry.&lt;/p&gt;
&lt;p&gt;Fast forward to that consultancy where Sean and I crossed paths. During a lunch and learn session, Sean prepared a talk about Domain-Driven Design. I could feel the cogs in my mind change irreversibly.&lt;/p&gt;
&lt;p&gt;Assigned to work with him on the UI portion of an application, I was astonished by the elegance of his C# code. Despite the complexity of the problem we were tackling, I found myself grasping the essence of the domain simply by examining his code.&lt;/p&gt;
&lt;p&gt;But something didn&apos;t quite sit right with me while at that consultancy. The conversations between other consultants seemed… way too surface-level. &lt;/p&gt;
&lt;p&gt;My colleagues argued about things like what Dan Abramov said about single-file React components and why Vue is better than React.&lt;/p&gt;
&lt;p&gt;It felt like we were stuck in a repetitive cycle, building the same app for the same 2 clients that funded 80% of the business year after year, just continually refining the implementation with the latest libraries and frameworks. &lt;/p&gt;
&lt;p&gt;It felt like the kind of cautionary situation Robert Greene or Patrick Bet-David would write entire chapters about.&lt;/p&gt;
&lt;p&gt;I couldn&apos;t help but question the value we were truly providing. Many of the other frontend developers were deeply curious and wanted to learn backend, but instead of taking that into their own hands, I noticed most were silently waiting for our employer to fund their learning efforts.&lt;/p&gt;
&lt;p&gt;I never expected that to happen, and guess what? It never did.&lt;/p&gt;
&lt;p&gt;Instead, for the next 8 months, I spent my mornings and evenings writing buggy backend code, trying to learn how to make it better.&lt;/p&gt;
&lt;p&gt;To some, that might seem extreme, but I really wanted to figure it out.&lt;/p&gt;
&lt;p&gt;And after everything I&apos;d experienced thus far in my college, university, and early professional experience, I had very little trust that things would just get sorted out by themselves.&lt;/p&gt;
&lt;p&gt;And during that time of work &amp;#x26; study, the industry certainly did shift.&lt;/p&gt;
&lt;p&gt;In a few years, the advent of AI was upon us. With GitHub Copilot and ChatGPT, gone was the inherent value of being a mere code-first frontend developer.&lt;/p&gt;
&lt;p&gt;Laws from timeless texts like The Mythical Man-Month (1995, Fred Brooks) such as the law of least developers, whereby &quot;adding more developers to a project typically makes it take longer&quot; - well, these laws locked into place.&lt;/p&gt;
&lt;p&gt;Suddenly, the value of a single full-stack Pattern-First Developer with access to ChatGPT became greater than 5+ frontend developers all combined.&lt;/p&gt;
&lt;p&gt;From 2021 to present day, I&apos;ve seen a ton of low-skilled frontend and hyper-specialized developers lose their jobs due to this phenomenon I&apos;ve been calling the Value Differential - the teeter-totter of what&apos;s valuable and what isn&apos;t (more on this later).&lt;/p&gt;
&lt;p&gt;Back to Sean.&lt;/p&gt;
&lt;p&gt;With him in front of me, I asked him what he was up to these days. &lt;/p&gt;
&lt;p&gt;When he told me the consultancy we used to work for died and that he was being made CTO at the client&apos;s company, I was not surprised at all. &lt;/p&gt;
&lt;p&gt;Excellent work always prevails. Mastery is truly recession-proof.&lt;/p&gt;
&lt;p&gt;At some point in our conversation, we spoke of Bruce Lee.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;You must be shapeless, formless, like water. When you pour water in a cup, it becomes the cup. When you pour water in a bottle, it becomes the bottle. When you pour water in a teapot, it becomes the teapot. Water can drip and it can crash. Become like water my friend.&quot; — Bruce Lee&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That encounter with Sean on the street brought back a flood of memories, reminding me of the path I had taken and the lessons I had learned. It solidified my conviction that mastering the first principles and possessing key mental models in this evolving landscape is critically important because it simply is not enough to be a mere Code-First Developer anymore. &lt;/p&gt;
&lt;p&gt;--&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;https://essentialist.dev/&quot;&gt;The Software Essentailist&lt;/a&gt;, we walk through what I call the 5 Phases of Craftship:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Code-First&lt;/li&gt;
&lt;li&gt;Best Practice-First&lt;/li&gt;
&lt;li&gt;Pattern-First&lt;/li&gt;
&lt;li&gt;Responsibility-First&lt;/li&gt;
&lt;li&gt;and Value-First&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Each of these phases marks a distinct shift in your value system as a developer, how you think about code, and how you decompose and solve problems.&lt;/p&gt;
&lt;p&gt;Because &lt;a href=&quot;/articles/definition-creates-reality/&quot;&gt;definition creates your &lt;em&gt;perceptual&lt;/em&gt; reality&lt;/a&gt;, the more you refine your thinking (ie: your definitions, beliefs &amp;#x26; knowledge about what code is and how you decompose and solve problems with it), the more complex the problems you can confidently decompose and solve.&lt;/p&gt;
&lt;p&gt;Let&apos;s discuss the first Phase: the Code-First Phase. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;(I sometimes call this &quot;The Pain Phase&quot;, the &quot;Imposter Syndrome Phase&quot;, the &quot;First Phase&quot;, or the &quot;Necessary Phase&quot; of craftship).&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;What-well-discuss&quot; style=&quot;position:relative;&quot;&gt;What we&apos;ll discuss&lt;a href=&quot;#What-well-discuss&quot; aria-label=&quot;What well discuss permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this short article, here&apos;s what we&apos;re going to do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We&apos;ll do a quick recap of who the Code-First Developer is&lt;/li&gt;
&lt;li&gt;We&apos;ll review the traps that prevent you from progressing&lt;/li&gt;
&lt;li&gt;Learn the next steps to transition from Code-First to Best Practice-First&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;What-is-the-Code-First-Developer&quot; style=&quot;position:relative;&quot;&gt;What is the Code-First Developer?&lt;a href=&quot;#What-is-the-Code-First-Developer&quot; aria-label=&quot;What is the Code First Developer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Alright, so the Code-First Developer.&lt;/p&gt;
&lt;p&gt;Who is this again?&lt;/p&gt;
&lt;p&gt;Ultimately, this is the type of developer that has learned to code but has yet to learn to craft.&lt;/p&gt;
&lt;p&gt;As we discussed in a previous module, the 4 pillars that every developer needs to focus on design, testing, architecture, and strategy. We call these &lt;strong&gt;The 4 Pillars of Software Development&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;And these 4 pillars have a chief purpose.&lt;/p&gt;
&lt;p&gt;And that is to act as assistive tools for us to help the 3 roles (customers, developers, users) achieve their goals.&lt;/p&gt;
&lt;p&gt;What are all those goals you might ask?&lt;/p&gt;
&lt;p&gt;In essence, you need to learn how to work in ways that will prove to be valuable. If you do it right, when you work, you&apos;ll keep the 3 roles in benefit by either creating:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TimeGivenBack (to pursue other human desires)&lt;/li&gt;
&lt;li&gt;or TimeEnriched (to enjoy the present moment)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That may be too abstract, so let&apos;s look at an example that should make sense to you.&lt;/p&gt;
&lt;p&gt;We&apos;ll use the developer - actually a frontend developer since when we&apos;re at the Code-First phase, most developers tend to be frontend developers.&lt;/p&gt;
&lt;p&gt;So, what are some common problems for frontend developers at the code-first phase?&lt;/p&gt;
&lt;p&gt;What might you be asking yourself?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how do I write E2E tests that aren&apos;t flaky? → because it takes time to write these, watch them run, and I hate the feeling of having to go back and re-do them every time the smallest thing changes&lt;/li&gt;
&lt;li&gt;how should I be writing unit tests? → because I&apos;ve tried to figure it out, but it was confusing, and taking too much time to know what to do&lt;/li&gt;
&lt;li&gt;what exactly should I test in the first place? → because I literally have no idea, and I know tests are important but it doesn&apos;t seem very useful to test something like Redux&lt;/li&gt;
&lt;li&gt;how should I organize my code so that it&apos;s scalable? → because I notice that I spend a lot of time flipping between abstractions and others seem to not really know what to do&lt;/li&gt;
&lt;li&gt;how do I do things the Angular / React / Vue way? → and so on...&lt;/li&gt;
&lt;li&gt;how can I get better at architecture? I don&apos;t know how to use &lt;insert tool or library here&gt; in a testable way? → and so on...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Key questions.&lt;/p&gt;
&lt;p&gt;Each hints at a tiny slice of pain (wasting time and feeling frustrated).&lt;/p&gt;
&lt;p&gt;And each with very little good answers at this level.&lt;/p&gt;
&lt;p&gt;That&apos;s because when you&apos;re at the code first phase, you don&apos;t know much of what matters.&lt;/p&gt;
&lt;p&gt;Yes, you can use the basics of your tools to solve problems but… testing, design, architecture, strategy? The stuff which actually allows you to keep those 3 roles in benefit? Not likely at this phase.&lt;/p&gt;
&lt;p&gt;We&apos;re talking about understanding the skills that allow you to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make testing fun and enjoyable?&lt;/li&gt;
&lt;li&gt;Approach your work consistent?&lt;/li&gt;
&lt;li&gt;Adapt to the changing requirements flexibly?&lt;/li&gt;
&lt;li&gt;Select a pragmatic testing architecture that will allow you to feel confident in your code given the time constraints?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These thing are really important. But they don&apos;t come until later phases.&lt;/p&gt;
&lt;p&gt;So we better move through &apos;em.&lt;/p&gt;
&lt;h2 id=&quot;The-Value-Differential-has-changed&quot; style=&quot;position:relative;&quot;&gt;The Value Differential has changed&lt;a href=&quot;#The-Value-Differential-has-changed&quot; aria-label=&quot;The Value Differential has changed permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I won&apos;t spend too much time on this here, and you already know, but being Code-First used to be fine.&lt;/p&gt;
&lt;p&gt;Thinking back to the early days of React, when things were kind of a mess, the API was changing every few weeks, and Webpack was the worst thing on the planet… this was when the most valuable thing you could be WAS a React Specialist.&lt;/p&gt;
&lt;p&gt;Back then, in 4 to 6 months, with access to FreeCodeCamp and some 12-hour YouTube video compilations, you could possess an incredibly valuable, in-demand skill nearly everyone needed.&lt;/p&gt;
&lt;p&gt;But now? &lt;/p&gt;
&lt;p&gt;What do we need now to get the same result?&lt;/p&gt;
&lt;p&gt;Internet access and a ChatGPT account.&lt;/p&gt;
&lt;p&gt;Yep.&lt;/p&gt;
&lt;p&gt;&quot;Hey, ChatGPT, can you generate a React Hook that helps me synchronize XYZ?&quot;&lt;/p&gt;
&lt;p&gt;Sure, here you go.&lt;/p&gt;
&lt;p&gt;Thank you, artificial intelligence.&lt;/p&gt;
&lt;p&gt;So what does that mean for all the freshly graduated frontend bootcamp devs looking for jobs?&lt;/p&gt;
&lt;p&gt;It means we need a different strategy, of course.&lt;/p&gt;
&lt;p&gt;Your biggest problem is the sheer amount of unknown unknowns.&lt;/p&gt;
&lt;p&gt;When I backtracked the path I was walking in solidbook, I realized that the biggest problem all Code-First developers face is that you don&apos;t even know what you need to know, and you don&apos;t know how to BEGIN learning what you need to know.&lt;/p&gt;
&lt;p&gt;It&apos;s the wild west.&lt;/p&gt;
&lt;p&gt;If you listen to what everyone else tells you to do, you&apos;ll learn new libraries and frameworks every few weeks. NOT leading yourself towards their depths and getting to the next Phases. New tools. &lt;/p&gt;
&lt;h2 id=&quot;The-Expert-Junior-Developer&quot; style=&quot;position:relative;&quot;&gt;The Expert Junior Developer&lt;a href=&quot;#The-Expert-Junior-Developer&quot; aria-label=&quot;The Expert Junior Developer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This trap of taking a breadth-first approach keeps you stuck at the surface and can potentially turn you into the Expert Junior Developer.&lt;/p&gt;
&lt;p&gt;You may have been around for quite some time, but like many of the consultants I worked with in the past at that now dead frontend consultancy, when you get back into the industry, you&apos;re still asking yourself:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how do I write E2E tests that aren&apos;t flaky?&lt;/li&gt;
&lt;li&gt;how should I be writing unit tests?&lt;/li&gt;
&lt;li&gt;what exactly should I test in the first place?&lt;/li&gt;
&lt;li&gt;how should I organize my code so that it&apos;s scalable?&lt;/li&gt;
&lt;li&gt;how do I do things that Angular / React / Vue way?&lt;/li&gt;
&lt;li&gt;how can I get better at architecture? I don&apos;t know how to use &lt;insert tool or library here&gt; in a testable way?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are the same questions.&lt;/p&gt;
&lt;p&gt;And we all know what comes next: burnout.&lt;/p&gt;
&lt;h2 id=&quot;Breadth--depth-leading-to-burnout&quot; style=&quot;position:relative;&quot;&gt;Breadth &gt; depth leading to burnout&lt;a href=&quot;#Breadth--depth-leading-to-burnout&quot; aria-label=&quot;Breadth  depth leading to burnout permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I interpret burnout as when the level of effort and energy you spend doesn&apos;t match the level of fulfillment you should experience.&lt;/p&gt;
&lt;p&gt;I believe the key to lifelong fulfillment is Mastery.&lt;/p&gt;
&lt;p&gt;To be able to set a goal, chart the path, and consistently walk that path confidently, regardless of what it pertains to, is one of the most fulfilling experiences, in my opinion.&lt;/p&gt;
&lt;p&gt;But the key, as I&apos;ve probably said twelve times in different ways, is depth, not breadth.&lt;/p&gt;
&lt;p&gt;Do less, more.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🌀 Focus on the main idea: Responsibilities. The metaphysical, atomic unit of matter that describes what software is comprised of is called a Responsibility (for doing and knowing). Let&apos;s continually refine our understanding of this. (You can take a look at &lt;a href=&quot;https://khalilstemmler.com/articles/tags/rdd/&quot;&gt;Responsibility-Driven Design&lt;/a&gt; if you&apos;d like to jump ahead a bit).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;How-to-progress-to-Best-Practice-First-what-to-do-instead&quot; style=&quot;position:relative;&quot;&gt;How to progress to Best Practice-First (what to do instead)&lt;a href=&quot;#How-to-progress-to-Best-Practice-First-what-to-do-instead&quot; aria-label=&quot;How to progress to Best Practice First what to do instead permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So let&apos;s discuss what we gotta do to move toward the next phase.&lt;/p&gt;
&lt;h3 id=&quot;Step-1-Shift-your-focus-to-Responsibilities-instead-of-Code&quot; style=&quot;position:relative;&quot;&gt;Step 1: Shift your focus to Responsibilities instead of Code&lt;a href=&quot;#Step-1-Shift-your-focus-to-Responsibilities-instead-of-Code&quot; aria-label=&quot;Step 1 Shift your focus to Responsibilities instead of Code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We want to get to Value-First so that you can do life-changing stuff.&lt;/p&gt;
&lt;p&gt;But doing so involves developing a deeper, more mature perception of code and how to code properly.&lt;/p&gt;
&lt;p&gt;First step: start to pay attention to the various responsibilities your tools handle.&lt;/p&gt;
&lt;p&gt;Start to notice the things that your tools do and know.&lt;/p&gt;
&lt;p&gt;What are the things that your web server does and knows?&lt;/p&gt;
&lt;p&gt;What about React? What does it do and what does it know?&lt;/p&gt;
&lt;p&gt;It&apos;s funny because you can use React every day for five years and become an expert, but when you &lt;a href=&quot;/articles/definition-creates-reality/&quot;&gt;expand your perception&lt;/a&gt; of what it is you&apos;re dealing with...&lt;/p&gt;
&lt;p&gt;When you no longer see React as the thing you use to &quot;build the frontend&quot;...&lt;/p&gt;
&lt;p&gt;But instead, you see it as a tool which allows you to &quot;build the UI while coding outside-in&quot; @ the Best Practice-First Phase.&lt;/p&gt;
&lt;p&gt;Or you&apos;ll see React as the tool you use to &quot;build your View Components and Page Components&quot; separately from how you organize other concerns using more robust frontend patterns like View Models, Domain Objects, Gateways and so on. &lt;/p&gt;
&lt;h3 id=&quot;Step-2-Commit-to-becoming-a-Value-First-developer-which-means-you-have-to-become-a-fullstack-developer&quot; style=&quot;position:relative;&quot;&gt;Step 2: Commit to becoming a Value-First developer (which means you have to become a fullstack developer)&lt;a href=&quot;#Step-2-Commit-to-becoming-a-Value-First-developer-which-means-you-have-to-become-a-fullstack-developer&quot; aria-label=&quot;Step 2 Commit to becoming a Value First developer which means you have to become a fullstack developer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You want to be able to produce as much value as possible.&lt;/p&gt;
&lt;p&gt;That means you need the ability to create information systems from end to end.&lt;/p&gt;
&lt;p&gt;But not just any information system. I&apos;m not just talking about using CRUD and REST.&lt;/p&gt;
&lt;p&gt;These need to be information systems that are Software Artifacts of Value.&lt;/p&gt;
&lt;p&gt;This means they help users, help customers achieve their goals, and developers can carry out their common development use cases.&lt;/p&gt;
&lt;p&gt;What you place your awareness on, you manifest.&lt;/p&gt;
&lt;p&gt;Let&apos;s focus on that.&lt;/p&gt;
&lt;p&gt;It&apos;s fun!. The world rewards you for that the value you put out.&lt;/p&gt;
&lt;h3 id=&quot;Step-3-Build-an-information-system-from-end-to-end-making-all-the-mistakes&quot; style=&quot;position:relative;&quot;&gt;Step 3: Build an information system from end to end, making all the mistakes&lt;a href=&quot;#Step-3-Build-an-information-system-from-end-to-end-making-all-the-mistakes&quot; aria-label=&quot;Step 3 Build an information system from end to end making all the mistakes permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the first Phase of Craftship, you want to focus on building information systems from end to end.&lt;/p&gt;
&lt;p&gt;That means frontend and backend.&lt;/p&gt;
&lt;p&gt;Build a React app that talks to a backend and a database.&lt;/p&gt;
&lt;p&gt;Build a Gatsby or Next.js app that uses a CMS.&lt;/p&gt;
&lt;p&gt;Doesn&apos;t matter. Just build something that a real human being can log onto an accomplish a task with.&lt;/p&gt;
&lt;p&gt;While you&apos;re building it, don&apos;t worry about best practices or if you&apos;re doing things right.&lt;/p&gt;
&lt;p&gt;Just make it work.&lt;/p&gt;
&lt;p&gt;Make it work and survey the landscape of tools you needed to use along the way.&lt;/p&gt;
&lt;p&gt;How do they help you cross the gap?&lt;/p&gt;
&lt;h3 id=&quot;Step-4-Validate-your-understanding&quot; style=&quot;position:relative;&quot;&gt;Step 4: Validate your understanding&lt;a href=&quot;#Step-4-Validate-your-understanding&quot; aria-label=&quot;Step 4 Validate your understanding permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As I said, the main challenge at the Code-First level is unknown unknowns.&lt;/p&gt;
&lt;p&gt;Focus on building something - anything - along the lines that it could serve others and a customer could possibly benefit from it. &lt;/p&gt;
&lt;p&gt;And while you do this, zoom all the way out, and then focus on what your tools are really for, why you use them, and what they do well.&lt;/p&gt;
&lt;p&gt;I will give later give you some strategies for ensuring you understand the role your tools play, the responsibilities, and how they either help or hurt the three roles in achieving their goals.&lt;/p&gt;
&lt;h2 id=&quot;Summary&quot; style=&quot;position:relative;&quot;&gt;Summary&lt;a href=&quot;#Summary&quot; aria-label=&quot;Summary permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The Code-First developer might be technically skilled at the implementation side of things, but the Value Differential says that code is not enough.&lt;/li&gt;
&lt;li&gt;The biggest challenge Code-First developers face is the sheer amount of unknown unknowns — knowing what to learn, what to prioritize, and how to learn it effectively without suffering from overwhelm or burnout.&lt;/li&gt;
&lt;li&gt;The goal is to be able to think and work responsibility-first because that&apos;s what will allow you to focus on what matters (creating value for the three roles) later on.&lt;/li&gt;
&lt;li&gt;So, let&apos;s take it one step at a time. To get to the next Phase of Craftship, you must commit to becoming full stack, build a real, basic information system that does something valuable, and ensure that you understand the purpose of the Code-First tools and topics used to do so.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA["Tests Are a Waste of Time"]]></title><description><![CDATA[I want to tackle a hot take that happens to be one of the biggest ones holding developers back from endless puppy videos becoming truly…]]></description><link>https://khalilstemmler.com/articles/tests-are-a-waste-of-time/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/tests-are-a-waste-of-time/</guid><pubDate>Wed, 08 Mar 2023 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;I want to tackle a hot take that happens to be one of the biggest ones holding developers back from &lt;del&gt;endless puppy videos&lt;/del&gt; becoming truly indispensable software designers.&lt;/p&gt;
&lt;p&gt;We&apos;re on a mission here to learn the first principles of design, testing &amp;#x26; architecture.&lt;/p&gt;
&lt;p&gt;That&apos;s going to open up a LOT of doors for us.&lt;/p&gt;
&lt;p&gt;Now, here&apos;s the thing I hear all the time:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&quot;Writing the test first (TDD) is a COMPLETE waste of time&lt;/strong&gt;&quot;.&lt;/p&gt;
&lt;p&gt;Ah man, that&apos;s a shame.&lt;/p&gt;
&lt;p&gt;Front-end developers, I&apos;m looking at y&apos;all.&lt;/p&gt;
&lt;p&gt;But, I &lt;em&gt;do&lt;/em&gt; know how we got there...&lt;/p&gt;
&lt;p&gt;I&apos;ve been there myself.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You&apos;ve tried TDD and realized — compared to the way you currently do things — it&apos;s pretty annoying&lt;/li&gt;
&lt;li&gt;And since you can still make your code work without writing the test first...&lt;/li&gt;
&lt;li&gt;It just seems unnecessarily challenging to approach your work this way&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Totally.&lt;/p&gt;
&lt;p&gt;And if you&apos;re a front-end developer, you may have heard things like: &quot;write tests, not many; mostly integration&quot;.&lt;/p&gt;
&lt;p&gt;Or that functional programming &lt;em&gt;doesn&apos;t need tests&lt;/em&gt; (and that you&apos;re doing FP by using the function keyword...)&lt;/p&gt;
&lt;p&gt;Or that all you need is E2E tests.&lt;/p&gt;
&lt;p&gt;Ahhh... geez.&lt;/p&gt;
&lt;p&gt;Many crafters ah&apos;ve met.&lt;/p&gt;
&lt;p&gt;And many I&apos;ve lost to the most unfortunate &lt;em&gt;Bad Testing Advice&lt;/em&gt; rabbit holes.&lt;/p&gt;
&lt;p&gt;Most devs follow the &lt;em&gt;Best Practices&lt;/em&gt; ™️ of what the official docs for their framework say to do (such as using snapshot tests — don&apos;t do that).&lt;/p&gt;
&lt;p&gt;And then there are tools like Jest and Cypress, &lt;strong&gt;which are fantastic&lt;/strong&gt;, but to be fair, they can&apos;t really give you the foundational design, architecture &amp;#x26; testing wisdom you need in order to know how to use them correctly.&lt;/p&gt;
&lt;p&gt;That&apos;s why we place &lt;strong&gt;90% of our energy on skills &gt; tools in the &lt;a href=&quot;https://discord.gg/TnqMR2P2rV&quot;&gt;Phronesis Labs&lt;/a&gt; and &lt;a href=&quot;https://www.essentialist.dev/master-the-essentials-of-software-design-with-typescript&quot;&gt;Software Essentialist&lt;/a&gt; communities&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;But just like you want to ensure you&apos;ve got some good grip strength before doing a 200lb deadlift...&lt;/p&gt;
&lt;p&gt;We need to get our mindset right before we embark on this path of skill development &lt;strong&gt;—&lt;/strong&gt; where we&apos;ll master &lt;em&gt;The Lost Art of Writing Scalable, Testable Code&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;To explain why this take is a massive wrench in your growth plan (though there is a caveat), I&apos;ll give you a three-part response.&lt;/p&gt;
&lt;p&gt;Ready?&lt;/p&gt;
&lt;p&gt;Here we go.&lt;/p&gt;
&lt;h2 id=&quot;1-The-Entire-Purpose-of-Professional-Software-Development-is-to-Guess&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;1. The Entire Purpose of Professional Software Development is to Guess&lt;/strong&gt;&lt;a href=&quot;#1-The-Entire-Purpose-of-Professional-Software-Development-is-to-Guess&quot; aria-label=&quot;1 The Entire Purpose of Professional Software Development is to Guess permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What do I mean by this?&lt;/p&gt;
&lt;p&gt;Well, just like there are a ton of different ways you can play Super Mario Bros (&lt;em&gt;you can Speed Run it like a manic, play for &quot;leisure&quot; with your partner&lt;/em&gt; &lt;strong&gt;—&lt;/strong&gt; &lt;em&gt;yeah right, or collect the coins on each level&lt;/em&gt;)...&lt;/p&gt;
&lt;p&gt;There are also a number of different ways you can play The Game of Software Development.&lt;/p&gt;
&lt;p&gt;You can play:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;the Code-First Mode&lt;/strong&gt;: where you just care about building &amp;#x26; making things work (as they occur)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;the Exploratory Mode&lt;/strong&gt;: where you&apos;re just trying out new libraries &amp;#x26; frameworks, having fun with them, and it&apos;s pretty light&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;the Professional Software Development Mode&lt;/strong&gt;: where the focus is on scalably, sustainably producing artifacts of value&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&apos;m willing to bet that you want to get paid for your efforts, so that means you&apos;d like to see yourself as a &lt;em&gt;Professional Software Developer&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Me too.&lt;/p&gt;
&lt;h2 id=&quot;What-is-Value-Anyway&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;What is Value Anyway?&lt;/strong&gt;&lt;a href=&quot;#What-is-Value-Anyway&quot; aria-label=&quot;What is Value Anyway permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Very simply, the way I think about value is this.&lt;/p&gt;
&lt;p&gt;Value is anything that &lt;strong&gt;makes you feel good&lt;/strong&gt; or &lt;strong&gt;gives you time back&lt;/strong&gt; (so that you can spend that time in the pursuit of trying to feel good).&lt;/p&gt;
&lt;p&gt;This is a key part of &lt;strong&gt;Essential #1: Software Essentialism&lt;/strong&gt;, because setting up these variables that we&apos;ll use throughout the entirety of craftship journey allows us to move strategically and make good (design, architecture, testing &amp;#x26; overall product) decisions.&lt;/p&gt;
&lt;p&gt;Another key thing to recognize is that &lt;strong&gt;everything is a state machine&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Including &lt;em&gt;Humans&lt;/em&gt; (that&apos;s you - I hope).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/tests-are-a-waste/its-always-been-state-machines.jpg&quot; alt=&quot;It&amp;#x27;s always been state machines&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://twitter.com/DavidKPiano&quot;&gt;David K. Piano&lt;/a&gt; was right, everyone.&lt;/p&gt;
&lt;p&gt;Here&apos;s how this works.&lt;/p&gt;
&lt;h2 id=&quot;From-Pain-→-Benefit--Value&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;From Pain → Benefit = Value&lt;/strong&gt;&lt;a href=&quot;#From-Pain-%E2%86%92-Benefit--Value&quot; aria-label=&quot;From Pain → Benefit  Value permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It&apos;s simple. We don&apos;t like pain. We like benefits.&lt;/p&gt;
&lt;p&gt;You create value when you take someone from pain to benefit.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/tests-are-a-waste/value-summary.png&quot; alt=&quot;Value summary&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;From-Benefit-→-Benefit&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;From Benefit → Benefit&lt;/strong&gt;&lt;a href=&quot;#From-Benefit-%E2%86%92-Benefit&quot; aria-label=&quot;From Benefit → Benefit permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It is also staying &lt;em&gt;IN&lt;/em&gt; benefit.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/tests-are-a-waste/benefit-a.png&quot; alt=&quot;Benefit&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Example: Thank you Facebook for reminding me that Grandma&apos;s birthday was today.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Example: Your email service continuing to chime along and work swimmingly, as it did last week.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;Negative-Value&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Negative Value&lt;/strong&gt;&lt;a href=&quot;#Negative-Value&quot; aria-label=&quot;Negative Value permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;But software can have the opposite effect as well.&lt;/p&gt;
&lt;p&gt;It can make you frustrated, feel dumb, silly, and bad about yourself.&lt;/p&gt;
&lt;p&gt;This effect is NEGATIVE VALUE.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/tests-are-a-waste/pain.png&quot; alt=&quot;Pain&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Example: Your email service all of a sudden stops working the way it used to.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Example: The UX to order a bowl from Chipotle on UberEats is so confusing that you accidentally order literally just chicken, nothing else - and you do that twice in a row by accident and then they ban you from the store because they think you&apos;re trolling them.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Example: Instagram changes the placement of the buttons for the 13th time this month.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This sucks.&lt;/p&gt;
&lt;h2 id=&quot;The-Guess-its-Theoretical--Physical&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;The Guess (it&apos;s &lt;em&gt;Theoretical &amp;#x26; Physical)&lt;/em&gt;&lt;/strong&gt;&lt;a href=&quot;#The-Guess-its-Theoretical--Physical&quot; aria-label=&quot;The Guess its Theoretical  Physical permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Know what this means?&lt;/p&gt;
&lt;p&gt;That there are at least 2 things that we don&apos;t know for sure.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;If what we want to build is valuable&lt;/strong&gt; (theoretically, does someone even want this?)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Ie: &quot;Hey everyone, I&apos;m going to build an Anime Debate App so you can all stop using Discord now, and use my app instead :) ...anyone?&quot;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If it will work&lt;/strong&gt;, and won&apos;t result in Negative Value (physical)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These two planes of Guesses have a ton of sub-guesses within them.&lt;/p&gt;
&lt;p&gt;We make Guesses at:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Theoretical Plane: &lt;em&gt;with at least 3 different Guess Points&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;The Physical Plane: &lt;em&gt;with at least 8 different Guess Points&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/tests-are-a-waste/guess-points-feedback-loops.png&quot; alt=&quot;Guess Points&quot;&gt;&lt;/p&gt;
&lt;p&gt;And the only way for us to verify that our guesses are correct, is to perform &lt;em&gt;Essential #2: The Feedback Loop.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This is also known as &lt;em&gt;Three Ways&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/tests-are-a-waste/3-ways-expanded.png&quot; alt=&quot;3 Ways Expanded&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;This is just TDD at the 8 Physical Levels, but holistically, this is the entire philosophy for how Professional Software Developers play the game of Professional Software Development. This is also business owners, product people - essentially, anyone involved in playing the role of &quot;creating software artifacts of value&quot;.&lt;/p&gt;
&lt;h2 id=&quot;Strategic-Pragmatic-Guessing&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Strategic, Pragmatic Guessing&lt;/strong&gt;&lt;a href=&quot;#Strategic-Pragmatic-Guessing&quot; aria-label=&quot;Strategic Pragmatic Guessing permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now, I know what you&apos;re going to say:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;You can&apos;t possibly expect me to write the test first for every single one of those feedback loops. that doesn&apos;t make any sense. I&apos;ll just E2E test the most important features. That&apos;s enough.&quot;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And you&apos;re absolutely, 100% right.&lt;/p&gt;
&lt;p&gt;Sometimes, it&apos;s non-strategic to spend time Feedback Looping over more inner-layer Guess Points.&lt;/p&gt;
&lt;p&gt;For example, if your app doesn&apos;t have any customers (no value just yet), it doesn&apos;t really make sense for you to &lt;em&gt;TDD&lt;/em&gt; your way through. You should be focused more on patching through to creating value for the right people. &lt;/p&gt;
&lt;p&gt;At that point, with a fresh, new product and a ton of uncertainty, yeah, go right ahead -- go wild with whatever frameworks you want, because your focus is NOT on The Physical just yet.&lt;/p&gt;
&lt;p&gt;It&apos;s on The Theoretical. &lt;/p&gt;
&lt;p&gt;Focus on getting at least ONE Theoretical Guess correct.&lt;/p&gt;
&lt;div class=&quot;solid-book-cta course-cta&quot;&gt;
  &lt;div class=&quot;solid-book-logo-container&quot;&gt;
    &lt;img src=&quot;/img/resources/tswe/logo.png&quot;/&gt;
  &lt;/div&gt;
  &lt;p&gt;In Part 5 of The Software Essentialist titled &quot;Bridging The Gap (Theoretical → Physical)&quot;, we apply this process and learn how to identify, design, and build your own product of value, from scratch.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;After one of your Theoretical Guesses connects, and you&apos;ve created real value for someone out there, your goal should shift.&lt;/p&gt;
&lt;p&gt;It should shift to the balance between:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Finding New Value&lt;/li&gt;
&lt;li&gt;Maintaining Existing Value&lt;/li&gt;
&lt;li&gt;Preventing Negative Value&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sounds straightforward, right?&lt;/p&gt;
&lt;p&gt;Until it&apos;s not.&lt;/p&gt;
&lt;p&gt;Seriously.&lt;/p&gt;
&lt;p&gt;It&apos;s much easier to be wrong than it is to be right.&lt;/p&gt;
&lt;p&gt;And there are so many ways to be wrong.&lt;/p&gt;
&lt;p&gt;Take Discord. When I was doing a live AMA in the Phronesis Labs Discord with over 100+ members, it suddenly just decided to cut out and drop everyone from the call.&lt;/p&gt;
&lt;p&gt;N E G A T I V E    V A L U E&lt;/p&gt;
&lt;p&gt;I call this &lt;em&gt;Feedback Loop Level 8: The Execution Guess Point.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A particularly tricky one.&lt;/p&gt;
&lt;p&gt;When this happens, expect your customers to start looking for solutions in other places (I&apos;m thinking about switching to Zoom).&lt;/p&gt;
&lt;p&gt;But if it could happen to Discord, it&apos;ll probably happen to us too.&lt;/p&gt;
&lt;p&gt;That&apos;s why we Lead With The Guess, make no assumptions, and prioritize covering as many &lt;em&gt;Guess Points&lt;/em&gt; with tests as humanly and reasonably possible within the time frame we have.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BTW: Remember when I said that learning this stuff opens up a lot of doors for you? If you understand how to identify Value Gaps in the real world AND you learn how to put software there, there&apos;s just one thing left. Selling it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/tests-are-a-waste/naval.png&quot; alt=&quot;Naval&quot;&gt;&lt;/p&gt;
&lt;p&gt;But that&apos;s a topic for another time.&lt;/p&gt;
&lt;p&gt;Let&apos;s press on.&lt;/p&gt;
&lt;h2 id=&quot;2-To-write-the-tests-first-you-need-a-testable-architecture&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;2. To write the tests first, you need a &lt;em&gt;testable architecture&lt;/em&gt;&lt;/strong&gt;&lt;a href=&quot;#2-To-write-the-tests-first-you-need-a-testable-architecture&quot; aria-label=&quot;2 To write the tests first you need a testable architecture permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At this point, you might be thinking:&lt;/p&gt;
&lt;p&gt;&quot;That&apos;s cool, Khalil - but I can always just add those tests later.&quot;&lt;/p&gt;
&lt;p&gt;Actually, you can&apos;t.&lt;/p&gt;
&lt;p&gt;Know what? Yeah, you &lt;em&gt;can&lt;/em&gt; &lt;strong&gt;—&lt;/strong&gt; but you&apos;re going to hate your life trying to carve out the ability to add those tests later on.&lt;/p&gt;
&lt;p&gt;Here&apos;s why.&lt;/p&gt;
&lt;p&gt;Ever heard of the &lt;strong&gt;hexagonal architecture&lt;/strong&gt;? (Similar or comparable to the &lt;em&gt;clean, onion, or ports &amp;#x26; adapters&lt;/em&gt; one).&lt;/p&gt;
&lt;p&gt;Well, the &lt;strong&gt;entire purpose of the hexagonal architecture is to give you the ability to reach those other Guess Points&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For example, most front-end developers don&apos;t have the baseline design foundation to write tests at &lt;em&gt;Feedback Loop Level 3: The Application Guess Point.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This is an incredibly missed opportunity.&lt;/p&gt;
&lt;p&gt;If you learn how to decouple from infrastructure here, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;force your code down various code paths using stubs&lt;/li&gt;
&lt;li&gt;cleanly test side-effects using test doubles&lt;/li&gt;
&lt;li&gt;have fun writing super fast, high-value developer tests that exhaust the majority of your edge cases&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The thing is, unless you&apos;ve &lt;em&gt;started&lt;/em&gt; with a layered architecture, it&apos;s likely going to be a major pain to refactor towards it.&lt;/p&gt;
&lt;p&gt;It&apos;s still possible, but it&apos;s better for you to start that way - assuming you&apos;re going to be making Guesses, because it&apos;s as they say:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Architecture is about the decisions you make at the beginning of a project&lt;/em&gt;. &lt;em&gt;Architecture is the stuff that matters, whatever that is.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;But it&apos;s never too late.&lt;/p&gt;
&lt;p&gt;If you want to learn this, do like we do in &lt;em&gt;The Software Essentialist.&lt;/em&gt; Start from the innermost feedback loop levels, and work your way towards the outer ones.&lt;/p&gt;
&lt;p&gt;There are some foundational skills you&apos;ll need to pick up along the way to get pretty good at this, like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Red-Green-Refactoring&lt;/li&gt;
&lt;li&gt;Programming by Wishful Thinking&lt;/li&gt;
&lt;li&gt;Using the 3 forms of Subject Verification to test anything&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;3-Testing-Requires-a-High-Level-of-Mastery-But-Its-The-Key&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;3. Testing Requires a High Level of Mastery (But It&apos;s The Key)&lt;/strong&gt;&lt;a href=&quot;#3-Testing-Requires-a-High-Level-of-Mastery-But-Its-The-Key&quot; aria-label=&quot;3 Testing Requires a High Level of Mastery But Its The Key permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Hopefully by now you&apos;re beginning to see how critical it is for us to prioritize &lt;strong&gt;developing the &lt;em&gt;capacity&lt;/em&gt; to&lt;/strong&gt; &lt;strong&gt;Lead With The Guess&lt;/strong&gt; and &lt;strong&gt;Write The Test First.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We may not always &lt;em&gt;do that&lt;/em&gt; if it doesn&apos;t fit into our strategy, but we definitely need the capacity to exercise a &lt;em&gt;Feedback Loop&lt;/em&gt; at each of these &lt;em&gt;Guess Points&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In actuality though, I think a huge reason why most developers don&apos;t bother with testing is because this:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It is hard to learn.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I was just chatting with one of your fellow &lt;em&gt;Phronesis Labs&lt;/em&gt; community members about this recently.&lt;/p&gt;
&lt;p&gt;We both agreed that in order to learn this skill properly, you need to know:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the basics of object design&lt;/li&gt;
&lt;li&gt;dependency injection&lt;/li&gt;
&lt;li&gt;dependency inversion&lt;/li&gt;
&lt;li&gt;hexagonal architectures &amp;#x26; decoupling from infrastructure&lt;/li&gt;
&lt;li&gt;how to use test doubles&lt;/li&gt;
&lt;li&gt;how to create great abstractions&lt;/li&gt;
&lt;li&gt;how to know when your abstractions aren&apos;t great&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&apos;s true. It&apos;s traditionally been a really hard thing to learn.&lt;/p&gt;
&lt;p&gt;It took me &lt;em&gt;years&lt;/em&gt; to get really good at, even after having built DDDForum (see it on my GitHub) and having written the first version of SOLID BOOK.&lt;/p&gt;
&lt;p&gt;But it&apos;s the key.&lt;/p&gt;
&lt;p&gt;When you learn how to test properly, you learn how to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Design, &lt;a href=&quot;https://khalilstemmler.com/letters/3-steps-to-solve-most-design-problems/#Learn-to-cook-dont-just-mix&quot;&gt;instead of just mixing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Win the game of Professional Software Development&lt;/li&gt;
&lt;li&gt;Build your own SaaS products&lt;/li&gt;
&lt;li&gt;Mitigate negative value in your codebase&lt;/li&gt;
&lt;li&gt;Think &amp;#x26; code backwards, producing the minimal amount of accidental complexity possible&lt;/li&gt;
&lt;li&gt;Get a safe grounds to test out designs&lt;/li&gt;
&lt;li&gt;Always produce the highest quality designs possible&lt;/li&gt;
&lt;li&gt;Create abstractions that others love to work with&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Develop scalable, maintainable code&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Imagine you wanted to implement a new feature -- and all you had to do was add a few lines of code. This is what us OOP nerds call &lt;em&gt;Open-Closed Principle&lt;/em&gt;, or extensibility for short.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ultimately, &lt;em&gt;you&lt;/em&gt; become a benefit to employers&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Did you know that over &lt;a href=&quot;https://khalilstemmler.com/articles/software-professionalism/developer-principles/&quot;&gt;$85 billion dollars goes right into the dumpster fire every year trying to maintain badly written software&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Want a piece of that pie?&lt;/li&gt;
&lt;li&gt;Learn to &lt;em&gt;Lead with the Guess&lt;/em&gt; and create truly scalable, value adding artifacts&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Good stuff, y&apos;all.&lt;/p&gt;
&lt;p&gt;That does it for this one.&lt;/p&gt;
&lt;p&gt;As always,&lt;/p&gt;
&lt;p&gt;To Mastery&lt;/p&gt;
&lt;p&gt;Khalil&lt;/p&gt;</content:encoded></item><item><title><![CDATA[No title]]></title><description><![CDATA[What is this? Stateful tests are obviously tests that rely on state What makes these different than other tests? You have to set up the…]]></description><link>https://khalilstemmler.com/wiki/testing/stateful-tests/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/testing/stateful-tests/</guid><pubDate>Sat, 26 Nov 2022 04:05:26 GMT</pubDate><content:encoded>&lt;p class=&quot;special-quote&quot;&gt;🌱 This blog post hasn&apos;t fully bloomed. It&apos;s very likely to change over the next little while.&lt;/p&gt;
&lt;h2 id=&quot;What-is-this&quot; style=&quot;position:relative;&quot;&gt;What is this?&lt;a href=&quot;#What-is-this&quot; aria-label=&quot;What is this permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Stateful tests are obviously tests that rely on state&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What makes these different than other tests?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;You have to set up the state of the world&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You usually have to test that the new state of the world is correct&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You usually have to test that the commands that changed the state of the world were, in fact called, and were called correctly&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;State-changes&quot; style=&quot;position:relative;&quot;&gt;State changes&lt;a href=&quot;#State-changes&quot; aria-label=&quot;State changes permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;What are state changes?&lt;/li&gt;
&lt;li&gt;A successful command-like operation is a state-change.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A successful &lt;code class=&quot;language-text&quot;&gt;save&lt;/code&gt;, saving a &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; aggregate to a &lt;code class=&quot;language-text&quot;&gt;userRepo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A successful &lt;code class=&quot;language-text&quot;&gt;makePurchase&lt;/code&gt; call to a &lt;code class=&quot;language-text&quot;&gt;Stripe API&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;A successful &lt;code class=&quot;language-text&quot;&gt;addRole&lt;/code&gt; on a &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; aggregate&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;State-machines&quot; style=&quot;position:relative;&quot;&gt;State machines&lt;a href=&quot;#State-machines&quot; aria-label=&quot;State machines permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Your application is &lt;em&gt;fundamentally&lt;/em&gt; a state machine. We move people from A to B - problem to solution. If your app had 9 different states, from beginning to end, and you wanted to test the &lt;em&gt;transition&lt;/em&gt; from state 6 to 7, you&apos;d need to &lt;em&gt;load&lt;/em&gt; up the state of the world from 1-6, in order to test that transition. Or at the very least, load up what the state of the world looked like at 6. &lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Questions&quot; style=&quot;position:relative;&quot;&gt;Questions&lt;a href=&quot;#Questions&quot; aria-label=&quot;Questions permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Why don&apos;t you test queries?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Because queries don&apos;t change the state of the world. &lt;/li&gt;
&lt;li&gt;Yes, they might return different data which &lt;em&gt;informs&lt;/em&gt; the behaviour, sending it down different code paths, but ultimately, there&apos;s no point in testing queries for stateful tests.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What&apos;s the role of queries in tests then?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Queries merely return the current state of the world.&lt;/li&gt;
&lt;li&gt;And depending on that state of the world, our application (a state machine), has to act upon that data in different ways.&lt;/li&gt;
&lt;li&gt;This is what we care about.&lt;/li&gt;
&lt;li&gt;&quot;Is my feature/use case behaving the way it &lt;em&gt;should&lt;/em&gt; based on this state of the world? Do I get a &lt;em&gt;failure&lt;/em&gt; result when I try to do something (ie: &lt;em&gt;perform a transition from one state to the next&lt;/em&gt;) at an invalid state? Do I get a &lt;em&gt;failure&lt;/em&gt; when I don&apos;t provide the appropriate data to perform the transition (the behaviour)?&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What&apos;s the difference between stateful and stateless tests?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;State, of course.&lt;/li&gt;
&lt;li&gt;That is, with stateless tests, we are testing functions or objects which typically live in &lt;em&gt;total isolation&lt;/em&gt;. They have no stateful collaborators.&lt;/li&gt;
&lt;li&gt;Why? Because there is no state &lt;em&gt;to&lt;/em&gt; them. Stateless  because they themselves have no state. There is no state &lt;em&gt;to&lt;/em&gt; them.&lt;/li&gt;
&lt;li&gt;We are often just testing &lt;em&gt;purely&lt;/em&gt; behaviour.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Data, behaviour, namespaces&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Let us remember that the essence of software is solve problems. And that is achieved by gathering &lt;em&gt;data&lt;/em&gt;, performing &lt;em&gt;behaviour&lt;/em&gt; against that data, and organizing the units of data and behaviour into cohesive &lt;em&gt;namespaces&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Do you see how this is much different from a &lt;em&gt;stateless test&lt;/em&gt;? &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[How to Find and Kill a Background Node Process]]></title><description><![CDATA[I'm sure you've run into this issue before. You try to  a project up but you get an error that looks something like the following:  What's…]]></description><link>https://khalilstemmler.com/blogs/cli/how-to-find-and-kill-node-process-mac/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/cli/how-to-find-and-kill-node-process-mac/</guid><pubDate>Thu, 03 Nov 2022 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;m sure you&apos;ve run into this issue before.&lt;/p&gt;
&lt;p&gt;You try to &lt;code class=&quot;language-text&quot;&gt;npm run start&lt;/code&gt; a project up but you get an error that looks something like the following: &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;project git:(master) ✗ npm run start

&amp;gt; gatsby develop

/Users/khalilstemmler/Documents/Personal/current/solid-book-wiki/projects/wiki/node_modules/yoga-layout-prebuilt/yoga-layout/build/Release/nbind.js:53
        throw ex;
        ^

Error: listen EADDRINUSE: address already in use 127.0.0.1:8000
    at Server.setupListenHandle [as _listen2] (node:net:1372:16)
    at listenInCluster (node:net:1420:12)
    at GetAddrInfoReqWrap.doListen (node:net:1559:7)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:73:8)
Emitted &amp;#39;error&amp;#39; event on Server instance at:
    at emitErrorNT (node:net:1399:8)
    at processTicksAndRejections (node:internal/process/task_queues:83:21) {
  code: &amp;#39;EADDRINUSE&amp;#39;,
  errno: -48,
  syscall: &amp;#39;listen&amp;#39;,
  address: &amp;#39;127.0.0.1&amp;#39;,
  port: 8000
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What&apos;s going on here?&lt;/p&gt;
&lt;p&gt;You have another process running on port &lt;code class=&quot;language-text&quot;&gt;8000&lt;/code&gt; and whatever you&apos;re trying to spin up also needs to utilize that port. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You can tell this from the &lt;code class=&quot;language-text&quot;&gt;EADDRINUSE&lt;/code&gt; error constant and the fact that it says &lt;code class=&quot;language-text&quot;&gt;127.0.0.1:8000&lt;/code&gt; is alreaady in use.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What to do?&lt;/p&gt;
&lt;p&gt;Here&apos;s a quick an easy fix to kill the process running so you can start something else up on that port.&lt;/p&gt;
&lt;h2 id=&quot;1-Find-whats-running-on-the-port&quot; style=&quot;position:relative;&quot;&gt;1. Find what&apos;s running on the port&lt;a href=&quot;#1-Find-whats-running-on-the-port&quot; aria-label=&quot;1 Find whats running on the port permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First thing is first. Use the &lt;code class=&quot;language-text&quot;&gt;lsof&lt;/code&gt; command to see what&apos;s running.&lt;/p&gt;
&lt;p&gt;We&apos;ll use it like this: &lt;code class=&quot;language-text&quot;&gt;lsof -i:&amp;lt;port&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;wiki git:&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;master&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ✗ &lt;span class=&quot;token function&quot;&gt;lsof&lt;/span&gt; -i:8000
COMMAND   PID           &lt;span class=&quot;token environment constant&quot;&gt;USER&lt;/span&gt;   FD   TYPE             DEVICE SIZE/OFF NODE NAME
node    &lt;span class=&quot;token number&quot;&gt;49516&lt;/span&gt; khalilstemmler   27u  IPv4 0xb0855a2b3b9a7a2b      0t0  TCP localhost:irdmi &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LISTEN&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Just as I thought. Some node process running.&lt;/p&gt;
&lt;h2 id=&quot;2-Take-note-of-the-process-number&quot; style=&quot;position:relative;&quot;&gt;2. Take note of the &lt;em&gt;process number&lt;/em&gt;&lt;a href=&quot;#2-Take-note-of-the-process-number&quot; aria-label=&quot;2 Take note of the process number permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Take a look at the &lt;code class=&quot;language-text&quot;&gt;PID&lt;/code&gt; column. That marks the &lt;em&gt;process number&lt;/em&gt;. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;wiki git:&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;master&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ✗ &lt;span class=&quot;token function&quot;&gt;lsof&lt;/span&gt; -i:8000
COMMAND   PID           &lt;span class=&quot;token environment constant&quot;&gt;USER&lt;/span&gt;   FD   TYPE             DEVICE SIZE/OFF NODE NAME
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;node    &lt;span class=&quot;token number&quot;&gt;49516&lt;/span&gt; khalilstemmler   27u  IPv4 0xb0855a2b3b9a7a2b      0t0  TCP localhost:irdmi &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LISTEN&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Copy it. You&apos;ll need it for the next step.&lt;/p&gt;
&lt;h2 id=&quot;3-Kill-whatevers-running-on-that-port-by-using-the-process-number&quot; style=&quot;position:relative;&quot;&gt;3. Kill whatever&apos;s running on that port &lt;em&gt;by using the process number&lt;/em&gt;&lt;a href=&quot;#3-Kill-whatevers-running-on-that-port-by-using-the-process-number&quot; aria-label=&quot;3 Kill whatevers running on that port by using the process number permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now, let&apos;s kill the process. &lt;/p&gt;
&lt;p&gt;You can do so with &lt;code class=&quot;language-text&quot;&gt;kill -9 &amp;lt;process-number&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;kill&lt;/span&gt; -9 &lt;span class=&quot;token number&quot;&gt;49516&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;4-Confirm-the-process-has-been-killed&quot; style=&quot;position:relative;&quot;&gt;4. Confirm the process has been killed&lt;a href=&quot;#4-Confirm-the-process-has-been-killed&quot; aria-label=&quot;4 Confirm the process has been killed permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Good. &lt;/p&gt;
&lt;p&gt;Lastly, let&apos;s make sure that worked.&lt;/p&gt;
&lt;p&gt;We can run the &lt;code class=&quot;language-text&quot;&gt;lsof&lt;/code&gt; command again to see if there&apos;s a process running.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;➜  wiki git:&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;master&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ✗ &lt;span class=&quot;token function&quot;&gt;lsof&lt;/span&gt; -i:8000
➜  wiki git:&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;master&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ✗ &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nothing! Looks like we did it.&lt;/p&gt;
&lt;h2 id=&quot;5-Re-run-whatever-you-were-trying-to-run&quot; style=&quot;position:relative;&quot;&gt;5. Re-run whatever you were trying to run&lt;a href=&quot;#5-Re-run-whatever-you-were-trying-to-run&quot; aria-label=&quot;5 Re run whatever you were trying to run permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;And finally, re-run whatever you were trying to run on that port.&lt;/p&gt;
&lt;p&gt;Done-zo.&lt;/p&gt;
&lt;p&gt;Now get back to it.&lt;/p&gt;
&lt;h2 id=&quot;Summary&quot; style=&quot;position:relative;&quot;&gt;Summary&lt;a href=&quot;#Summary&quot; aria-label=&quot;Summary permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&apos;s a summary.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use &lt;code class=&quot;language-text&quot;&gt;lsof -i:&amp;lt;port&amp;gt;&lt;/code&gt; to find the offending process id&lt;/li&gt;
&lt;li&gt;Take note of the process number in table&lt;/li&gt;
&lt;li&gt;Use &lt;code class=&quot;language-text&quot;&gt;kill -9 &amp;lt;process-number&amp;gt;&lt;/code&gt; to kill the process at the port&lt;/li&gt;
&lt;li&gt;Confirm it worked with &lt;code class=&quot;language-text&quot;&gt;lsof -i:&amp;lt;port&amp;gt;&lt;/code&gt; again. You should not see the same process.&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[3 Steps to Solve Most Design Problems | How to Find Abstractions Effectively]]></title><description><![CDATA[When I was in university, I decided to build my first startup with a couple of buddies that helped students find jobs. Having spent a year…]]></description><link>https://khalilstemmler.com/articles/3-steps-to-solve-most-design-problems/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/3-steps-to-solve-most-design-problems/</guid><pubDate>Thu, 08 Sep 2022 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;When I was in university, I decided to build my first startup with a couple of buddies that helped students find jobs.&lt;/p&gt;
&lt;p&gt;Having spent a year learning JavaScript and flying through Tyler McGinnis’ courses on React and Redux, I went in. &lt;/p&gt;
&lt;p&gt;Slinging code like wild, I eventually encountered a challenge: to design a complex page-routing system that would re-route users to the correct pages depending on a variety of different factors (state, user type, account verification). &lt;/p&gt;
&lt;p&gt;Since I couldn’t find a library to help me do this, I had to build it myself. &lt;/p&gt;
&lt;p&gt;Feeling overconfident, I over-engineered the heck out of it with no tests. &lt;/p&gt;
&lt;p&gt;Over the rest of the lifetime of the project, that routing system became the key area to cause bugs, frustrating customers and humbling me in the process. &lt;/p&gt;
&lt;p&gt;Ah, the art of creating good abstractions.&lt;/p&gt;
&lt;p&gt;How I wish I knew back then what I know now.&lt;/p&gt;
&lt;p&gt;Let’s talk about how to solve most design problems and find abstractions effectively.&lt;/p&gt;
&lt;h2 id=&quot;The-Responsibility-Driven-Design-method&quot; style=&quot;position:relative;&quot;&gt;The Responsibility-Driven Design method&lt;a href=&quot;#The-Responsibility-Driven-Design-method&quot; aria-label=&quot;The Responsibility Driven Design method permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’ve explored many different ways to design software but if you ask me, I’d say that learning &lt;a href=&quot;https://khalilstemmler.com/articles/object-oriented/design/responsibility-driven-design/&quot;&gt;Responsibility-Driven Design&lt;/a&gt; &lt;strong&gt;was the last thing that I really needed to deeply understand the nature of design.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Responsibility-Driven Design process is pretty straightforward, but the magic is in the details.&lt;/p&gt;
&lt;p&gt;Here’s how it works.&lt;/p&gt;
&lt;p&gt;Start with a requirement (functional or &lt;a href=&quot;https://khalilstemmler.com/articles/object-oriented/analysis/non-functional-requirements/&quot;&gt;non-functional&lt;/a&gt;), convert it into responsibilities, assign those to roles, then find the collaborations.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/3-steps/the-responsibility-driven-design-process.svg&quot; alt=&quot;The Responsibility-Driven Design Process&quot;&gt;&lt;/p&gt;
&lt;p&gt;Allow me to demonstrate using a call I had with a dev last week as an example.&lt;/p&gt;
&lt;h2 id=&quot;Step-0-Identify-the-requirement&quot; style=&quot;position:relative;&quot;&gt;Step 0: Identify the requirement&lt;a href=&quot;#Step-0-Identify-the-requirement&quot; aria-label=&quot;Step 0 Identify the requirement permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Say you’re working on some back-end code. &lt;/p&gt;
&lt;p&gt;You’ve been asked to add a feature. &lt;/p&gt;
&lt;p&gt;The feature is: &lt;strong&gt;if you perform a request while logged in, the system should update your account’s &lt;em&gt;lastActive&lt;/em&gt; time&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Step-1-Decompose-the-requirement-into-responsibilities&quot; style=&quot;position:relative;&quot;&gt;Step 1: Decompose the requirement into responsibilities&lt;a href=&quot;#Step-1-Decompose-the-requirement-into-responsibilities&quot; aria-label=&quot;Step 1 Decompose the requirement into responsibilities permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First things first.&lt;/p&gt;
&lt;p&gt;Understand that requirements contain a multitude of smaller &lt;em&gt;responsibilities&lt;/em&gt; and responsibilities. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Responsibilities&lt;/em&gt; can be for either &lt;em&gt;doing&lt;/em&gt; or &lt;em&gt;knowing&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Here’s what we did. At first, we found the following responsibilities.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;For doing&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Update the last active time&lt;/li&gt;
&lt;li&gt;Intercept requests&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;For knowing&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Know if the user is logged in or not&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But then, after further questions about performance (ie: like how do we do this really fast if we have to go to the database all the time — wouldn’t that be inefficient), we identified even more responsibilities. Responsibilities &lt;strong&gt;involving caching&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The working list of responsibilities changed a bit more:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;For doing&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Intercept all requests&lt;/li&gt;
&lt;li&gt;Update the last active time in the cache&lt;/li&gt;
&lt;li&gt;Persist last active time in cache to the database periodically&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;For knowing&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Know if the user is logged in or not&lt;/li&gt;
&lt;li&gt;Know when to persist to the database&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not bad so far.&lt;/p&gt;
&lt;h2 id=&quot;Step-2-Look-for-common-object-role-stereotypes&quot; style=&quot;position:relative;&quot;&gt;Step 2: Look for common object (role) stereotypes&lt;a href=&quot;#Step-2-Look-for-common-object-role-stereotypes&quot; aria-label=&quot;Step 2 Look for common object role stereotypes permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The next thing we do is take your list of responsibilities, and for each one, assign them to &lt;em&gt;roles&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If you forgot, &lt;strong&gt;a &lt;em&gt;role&lt;/em&gt; is a collection of responsibilities&lt;/strong&gt;. For example, a &lt;em&gt;Repository&lt;/em&gt; usually has the responsibility to &lt;em&gt;save&lt;/em&gt; and &lt;em&gt;find&lt;/em&gt; domain objects.&lt;/p&gt;
&lt;p&gt;Cool, but how do we come up with roles? How do we know which responsibilities to assign Is there a structured way to do this? &lt;/p&gt;
&lt;p&gt;There is.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/object-oriented/design/object-stereotypes/&quot;&gt;You use the six Object Stereotypes&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Check that article out and come back.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Back? &lt;/p&gt;
&lt;p&gt;Sweet.&lt;/p&gt;
&lt;p&gt;So yeah, object stereotypes are probably the best part of RDD. They act as building blocks — stereotypical elements — of any design. &lt;/p&gt;
&lt;p&gt;After we got up to speed on object stereotypes, when we looked at the &lt;em&gt;intercept all requests&lt;/em&gt; responsibility, I asked: &lt;/p&gt;
&lt;p&gt;“What kind of stereotype do you think handles something like &lt;em&gt;intercepting requests&lt;/em&gt;?”&lt;/p&gt;
&lt;p&gt;Almost immediately, we realized this behaviour as something that a &lt;em&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/object-oriented/design/object-stereotypes/#4-The-Coordinator&quot;&gt;Coordinator&lt;/a&gt;&lt;/em&gt; (the fourth stereotype) would do.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/3-steps/coordinator-responsibility-driven-design.png&quot; alt=&quot;Coordinator Responsibility Driven Design&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Coordinators&lt;/em&gt; typically only have one real purpose: to pass information to other objects so that they can do work. &lt;/p&gt;
&lt;p&gt;Next question. Do we need to create a new &lt;em&gt;coordinator&lt;/em&gt; or is there already one present we could merely extend?&lt;/p&gt;
&lt;p&gt;Me: “So, do you have already anything in your architecture that acts like a &lt;em&gt;coordinator&lt;/em&gt;?”&lt;/p&gt;
&lt;p&gt;Him: “Hmm. Actually, yeah. I’m using Express. You know, as my router. It has this &lt;em&gt;middleware&lt;/em&gt; feature in it. I could probably use that, right?”&lt;/p&gt;
&lt;p&gt;Me: “Absolutely.”&lt;/p&gt;
&lt;p&gt;Amazing. We already have a &lt;em&gt;coordinator&lt;/em&gt;. It can handle the &lt;em&gt;intercepting&lt;/em&gt; responsibility.&lt;/p&gt;
&lt;p&gt;That’s 1 out of 5 responsibilities assigned to roles. &lt;/p&gt;
&lt;p&gt;We continue going down the list and assigning responsibilities to roles.&lt;/p&gt;
&lt;h2 id=&quot;Step-3-Collaborations&quot; style=&quot;position:relative;&quot;&gt;Step 3: Collaborations&lt;a href=&quot;#Step-3-Collaborations&quot; aria-label=&quot;Step 3 Collaborations permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After you’ve assigned your responsibilities to roles (ideally based on &lt;em&gt;Object Stereotypes&lt;/em&gt;), you’re going to need to figure out how to connect your new or existing roles together. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It’s time to identify the collaborations&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;There are number of ways to do this, but the most obvious way is to — &lt;em&gt;again&lt;/em&gt;, look back to the stereotypes. &lt;/p&gt;
&lt;p&gt;If you know:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The object stereotype&lt;/li&gt;
&lt;li&gt;Where it lives within in a layered architecture&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then you can usually figure out who its neighbour&apos;s are. We can ask ourselves:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Who does it need help from?&lt;/li&gt;
&lt;li&gt;Who does it help?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/3-steps/Untitled%201.svg&quot; alt=&quot;Untitled&quot;&gt;&lt;/p&gt;
&lt;p&gt;After assigning the responsibilities to roles, we started fleshing out the collaborations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For &lt;strong&gt;intercepting all requests&lt;/strong&gt; → We identified the Express Middleware (&lt;em&gt;Coordinator&lt;/em&gt;) and &lt;em&gt;Coordinators&lt;/em&gt; typically communicate with &lt;em&gt;Controllers&lt;/em&gt;. Therefore, we realized we needed UpdateLastActive use case (&lt;em&gt;Controller&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;For &lt;strong&gt;updating the last active time in the cache&lt;/strong&gt; → We had to invent a Cache (both &lt;em&gt;Interfacer&lt;/em&gt; &amp;#x26; &lt;em&gt;Structurer&lt;/em&gt; stereotypes). This was to be used by the UpdateLastActive use case (&lt;em&gt;Controller&lt;/em&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A tricky one was the responsibility of &lt;strong&gt;persisting the last active time in cache to the database periodically&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For this, we had to do break it down even further. The idea of periodic updates implies schedules which implies scheduling responsibilities. We had to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Find all the &lt;strong&gt;scheduling responsibilities&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;and assign them to new and existing roles&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Eventually, we ended up with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a Scheduler (both the &lt;em&gt;Service Provider&lt;/em&gt; and &lt;em&gt;Coordinator&lt;/em&gt; stereotypes)&lt;/li&gt;
&lt;li&gt;a ScheduledTask (&lt;em&gt;Controller&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;and of course the UserRepo (&lt;em&gt;Interfacer&lt;/em&gt;) to actually update the user’s info&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Boom. Done. &lt;/p&gt;
&lt;p&gt;A quick little drawing to make sure things actually line up and we’re off to writing the first tests and coding it out.&lt;/p&gt;
&lt;h2 id=&quot;Patterns-communication--abstraction&quot; style=&quot;position:relative;&quot;&gt;Patterns, communication &amp;#x26; abstraction&lt;a href=&quot;#Patterns-communication--abstraction&quot; aria-label=&quot;Patterns communication  abstraction permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Do you see how powerful this is? &lt;/p&gt;
&lt;p&gt;By adopting a design method and levering the fact that we, as humans, are pattern-matching machines, you not only gain the ability to solve problems with well-known solutions, you find it incredibly easy to communicate your design ideas with others. &lt;/p&gt;
&lt;p&gt;Without needing to get into the details, as soon as we established what a &lt;em&gt;Coordinator&lt;/em&gt; was, the developer was able to identify it within his architecture instantaneously. &lt;/p&gt;
&lt;p&gt;Abstraction. It’s what &lt;a href=&quot;https://www.youtube.com/watch?v=3rq0GKYx-LE&quot;&gt;Alan Watts taught us&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Archetypes. It’s what &lt;a href=&quot;https://conorneill.com/2018/04/21/understanding-personality-the-12-jungian-archetypes/&quot;&gt;Carl Jung knew&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you were a writer, you’d leverage the Jungian personality archetypes to write engaging stories and plays. &lt;/p&gt;
&lt;p&gt;But you’re a developer, so familiarize yourself with object stereotypes and learn to write scalable software.&lt;/p&gt;
&lt;h2 id=&quot;Learn-to-cook-dont-just-mix&quot; style=&quot;position:relative;&quot;&gt;Learn to cook, don’t just mix&lt;a href=&quot;#Learn-to-cook-dont-just-mix&quot; aria-label=&quot;Learn to cook dont just mix permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once, my mom visited me in university to check in on me and how I was cooking for myself.&lt;/p&gt;
&lt;p&gt;Noticing the empty Kraft dinner boxes, I heard her say:&lt;/p&gt;
&lt;p&gt;“Kraft Dinner isn’t cooking; that’s just mixing.”&lt;/p&gt;
&lt;p&gt;I apologize to any Kraft dinner chefs out there reading this, but she’s right.&lt;/p&gt;
&lt;p&gt;Doesn’t matter if you’re frontend or backend, when you’re stuck in library and framework-land, you don’t learn &lt;em&gt;how to design&lt;/em&gt; and you don’t learn &lt;em&gt;how to architect&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;You just mix.&lt;/p&gt;
&lt;p&gt;When all you have are the things that libraries and frameworks give you, you’re pretty darn limited in your thinking. &lt;/p&gt;
&lt;h2 id=&quot;Its-always-gonna-be-roles-responsibilities-and-collaborations&quot; style=&quot;position:relative;&quot;&gt;It’s always gonna be roles, responsibilities, and collaborations&lt;a href=&quot;#Its-always-gonna-be-roles-responsibilities-and-collaborations&quot; aria-label=&quot;Its always gonna be roles responsibilities and collaborations permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I presented an image earlier. I’ll show it again here. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/3-steps/Untitled%201.svg&quot; alt=&quot;Untitled&quot;&gt;&lt;/p&gt;
&lt;p&gt;This image depicts pretty much &lt;em&gt;everything you’ll ever come across in building web applications.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I recommend you screenshot it or save it.&lt;/p&gt;
&lt;p&gt;Doesn’t matter if you’re building robots, video games, or something else — your task is always the same: assign responsibilities to roles and design collaborations.&lt;/p&gt;
&lt;p&gt;Even if you’re doing &lt;em&gt;pure&lt;/em&gt; (and proper) functional programming. Same task.&lt;/p&gt;
&lt;p&gt;To me, Responsibility-Driven Design is as deep as you need to go. It contains foundational ideas that help you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Develop a second sense for how to solve design problems&lt;/li&gt;
&lt;li&gt;Learn how to design scalable frontend and backend architectures&lt;/li&gt;
&lt;li&gt;Identify the patterns and stereotypes within your favourite libraries and frameworks, rely on them less, use them more effectively, and fill in design gaps with your own abstractions when they try to lead you astray to do things that would render your code untestable&lt;/li&gt;
&lt;li&gt;Venture into how to design distributed systems&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope that was helpful. &lt;/p&gt;
&lt;p&gt;You’ll hear more about the important parts of RDD and how to design scalable frontend architectures from me in the future.&lt;/p&gt;
&lt;p&gt;Let me know if there’s something you’d like to know specifically.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Until then, enjoy the rest of your week.&lt;/p&gt;
&lt;p&gt;To mastery,&lt;/p&gt;
&lt;p&gt;Khalil&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;h3 id=&quot;What-happened-this-week&quot; style=&quot;position:relative;&quot;&gt;What happened this week&lt;a href=&quot;#What-happened-this-week&quot; aria-label=&quot;What happened this week permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The Frontend Architecture Academy&lt;/strong&gt; — This just in. An 8-week 1-on-1 coaching program where I teach you how to build scalable frontend applications using the best parts of DDD, TDD, BDD, RDD, clean architecture and more. Slots are limited. If you’re interested in joining, want more info, or could simply use some advice, &lt;a href=&quot;https://calendly.com/khalilstemmler/call?month=2022-09&quot;&gt;throw some time on my calendar&lt;/a&gt;. I’d love to hear what your challenges are and to see if I can point you in the right direction.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Phronesis Labs Discord community&lt;/strong&gt; — Well folks, I’ve finally done it. The advanced software design and architecture discord community you’ve been asking me to make for about 2 years is finally here.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/letters/3-steps/tweet.png&quot; alt=&quot;Untitled&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://discord.gg/dqpmaudf4u&quot;&gt;You can join for free here&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Writing a song on flow, Dionysus, and the creative process (demo)&lt;/strong&gt; — In &lt;em&gt;The Birth of Tragedy,&lt;/em&gt; Nietzsche wrote that the struggle of human nature is that we are both &lt;em&gt;Apollonian&lt;/em&gt; (see the Greek god of light and reason) and &lt;em&gt;Dionysian&lt;/em&gt; (see the god of wine, ecstatic emotion, and tragedy). Things like music, art, passion, and love pertain to the realm of &lt;em&gt;Dionysus.&lt;/em&gt; Sculpture, craftship, and progress pertain to the &lt;em&gt;Apollo&lt;/em&gt;. Whenever I sit down to write (music, books, blog posts), I find myself transported to the realm of the &lt;em&gt;Dionysus —&lt;/em&gt; perhaps the very same realm that Mihaly Csikszentmihalyi calls &lt;em&gt;Flow&lt;/em&gt;. It’s the optimal state of consciousness. Of happiness. &lt;a href=&quot;https://khalilstemmler.notion.site/Portals-Demo-d7117eb9df3348e0949355dd4c583a64&quot;&gt;You can listen to the rough demo here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Object Stereotypes]]></title><description><![CDATA[Why the heck is LEGO still so comforting after all these years? Maybe it's because it feels good to come back to the same baseline elements…]]></description><link>https://khalilstemmler.com/articles/object-oriented/design/object-stereotypes/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/object-oriented/design/object-stereotypes/</guid><pubDate>Wed, 07 Sep 2022 22:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;special-quote&quot;&gt;🌱 This blog post hasn&apos;t fully bloomed. It&apos;s very likely to change over the next little while.&lt;/p&gt;
&lt;p&gt;Why the heck is LEGO still so comforting after all these years?&lt;/p&gt;
&lt;p&gt;Maybe it&apos;s because it feels good to come back to the same baseline elements: the brick, the baseplate, the tile, the mini-fig, etc. &lt;/p&gt;
&lt;p&gt;Object stereotypes, a concept from &lt;a href=&quot;https://khalilstemmler.com/articles/object-oriented/design/responsibility-driven-design/&quot;&gt;Responsibility-Driven Design&lt;/a&gt;, are effectively your programming LEGO.&lt;/p&gt;
&lt;p&gt;They’re your starting pieces when you&apos;re trying to find the right abstractions to create.&lt;/p&gt;
&lt;p&gt;Within your codebase, your libraries, frameworks, and so on - if you look closely, you&apos;ll notice that your objects tend to conform to one or more object stereotypes.&lt;/p&gt;
&lt;h2 id=&quot;How-to-use-object-stereotypes&quot; style=&quot;position:relative;&quot;&gt;How to use object stereotypes&lt;a href=&quot;#How-to-use-object-stereotypes&quot; aria-label=&quot;How to use object stereotypes permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Responsibility-Driven process involves taking a requirement, extracting out the responsibilities, and the assigning those responsibilities to &lt;em&gt;roles&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;How do you find the correct role?&lt;/p&gt;
&lt;p&gt;Look to the stereotypes.&lt;/p&gt;
&lt;p&gt;They act as hints to the roles we want to introduce.&lt;/p&gt;
&lt;h2 id=&quot;The-6-Stereotypes&quot; style=&quot;position:relative;&quot;&gt;The 6 Stereotypes&lt;a href=&quot;#The-6-Stereotypes&quot; aria-label=&quot;The 6 Stereotypes permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Information Holder&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Structurer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Service Provider&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Coordinator&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Controller&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Interfacer&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;1-The-Information-Holder&quot; style=&quot;position:relative;&quot;&gt;1. The Information Holder&lt;a href=&quot;#1-The-Information-Holder&quot; aria-label=&quot;1 The Information Holder permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;em&gt;Information Holder&lt;/em&gt; is perhaps the simplest stereotype we know of. Most similar to idea of a &lt;em&gt;Value Object&lt;/em&gt; made popular in Domain-Driven Design, &lt;em&gt;Information Holders&lt;/em&gt; are usually &lt;em&gt;domain&lt;/em&gt; layer concerns, but they can also represent other things as well (such as &lt;em&gt;Data Transfer Objects&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/design/object-stereotypes/Information_Holder.svg&quot; alt=&quot;Information Holder.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;What’s important to know is that the stereotypical responsibility of this &lt;em&gt;role&lt;/em&gt; is to hold information. Anytime you notice responsibilities to hold info, consider designing that object candidate as an &lt;em&gt;Information Holder&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;2-The-Structurer&quot; style=&quot;position:relative;&quot;&gt;2. The Structurer&lt;a href=&quot;#2-The-Structurer&quot; aria-label=&quot;2 The Structurer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Structurers&lt;/em&gt; are primarily about creating and maintaining relationships between objects. &lt;em&gt;Structurers&lt;/em&gt; protect against invariants and can make it easy to find related objects. &lt;/p&gt;
&lt;p&gt;Examples of &lt;em&gt;Structurers&lt;/em&gt; are &lt;em&gt;Aggregates&lt;/em&gt; (from Domain-Driven Design), hash tables (or any mechanism responsible for caching), or objects that pool or handle connections.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/design/object-stereotypes/Untitled.svg&quot; alt=&quot;Untitled&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;3-The-Service-Provider&quot; style=&quot;position:relative;&quot;&gt;3. The Service Provider&lt;a href=&quot;#3-The-Service-Provider&quot; aria-label=&quot;3 The Service Provider permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Service providers are objects that sit passive and contain useful, specialized computations. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/design/object-stereotypes/Service_Provider.svg&quot; alt=&quot;Service Provider (1).svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stable service providers:&lt;/strong&gt; They typically sit dormant waiting for other objects to call them, but because they’re often relied upon by so many objects, they may contain responsibilities that relatively &lt;em&gt;stable&lt;/em&gt;, not changing often.&lt;/p&gt;
&lt;p&gt;For example, utility classes like &lt;em&gt;TextUtil&lt;/em&gt;, &lt;em&gt;DateUtil, NumberUtil&lt;/em&gt; provide respective text, date, and number utilities and probably don’t change dramatically (or at all for that matter). For this reason, we’d say they’re stable. Just think about what would happen if we had to change the &lt;code class=&quot;language-text&quot;&gt;JSON.stringify&lt;/code&gt; method in JavaScript. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pure fabrication&lt;/strong&gt;: Alternatively, service providers are also objects that live in the domain layer yet don’t represent concepts from the problem domain. Instead, they’re objects that are specifically invented to ensure other domain objects maintain low coupling, high cohesion, and encapsulation. In Domain-Driven Design, we call these types of classes &lt;em&gt;Domain Services&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cross-cutting concern service providers:&lt;/strong&gt; Lastly, service providers are known to contain responsibilities that are commonly know as “cross-cutting concerns” like logging, security, or tracing (each of which are non-functional requirements). A concern = a functional or non-functional requirement. Non-functional requirements are the ones that are “cross-cut”. This means that &lt;em&gt;Use Cases&lt;/em&gt; either &lt;strong&gt;rely on&lt;/strong&gt; these service-providers OR we design the collaboration so that the service providers &lt;strong&gt;wrap&lt;/strong&gt; the &lt;em&gt;Use Case&lt;/em&gt; (hence the name “cross-cutting”). &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/design/object-stereotypes/Untitled.png&quot; alt=&quot;Untitled&quot;&gt;&lt;/p&gt;
&lt;p&gt;Either solution works, but there are tradeoffs to both.&lt;/p&gt;
&lt;h3 id=&quot;4-The-Coordinator&quot; style=&quot;position:relative;&quot;&gt;4. The Coordinator&lt;a href=&quot;#4-The-Coordinator&quot; aria-label=&quot;4 The Coordinator permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;em&gt;Coordinator&lt;/em&gt; stereotype has one real purpose: to pass information to other objects so that they can do work. When we look at it like this, &lt;strong&gt;&lt;em&gt;Coordinators&lt;/em&gt; are one of two objects most responsible for determining how control happens in our applications (the other is the &lt;em&gt;Controller&lt;/em&gt;)&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/design/object-stereotypes/Coordinator.svg&quot; alt=&quot;Coordinator.svg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;5-The-Controller&quot; style=&quot;position:relative;&quot;&gt;5. The Controller&lt;a href=&quot;#5-The-Controller&quot; aria-label=&quot;5 The Controller permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We’ve dealt with this particular type of stereotype before, but we’ve been calling it the &lt;em&gt;Use Case&lt;/em&gt; instead. In RDD, the &lt;em&gt;Controller&lt;/em&gt; stereotype is the exact same thing as the &lt;em&gt;Use Case&lt;/em&gt; pattern. &lt;/p&gt;
&lt;p&gt;The stereotypical responsibility held by a &lt;em&gt;Controller&lt;/em&gt; is to act as a higher-level (&lt;em&gt;application&lt;/em&gt;-layer specifically), declaratively focused object that coordinates the behaviour of lower-level concerns.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/design/object-stereotypes/Controller.svg&quot; alt=&quot;Controller.svg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;6-The-Interfacer&quot; style=&quot;position:relative;&quot;&gt;6. The Interfacer&lt;a href=&quot;#6-The-Interfacer&quot; aria-label=&quot;6 The Interfacer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The last of the stereotypes is the &lt;em&gt;Interfacer&lt;/em&gt;. The &lt;em&gt;Interfacer&lt;/em&gt; primary acts as a bridge between object neighborhoods (internal and external). &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Internal interfacer&lt;/strong&gt;: To cross internal object neighborhoods, we need to make the entry-point for our components as simple as possible. The object which sits at the front, relaying messages to objects behind the scenes is the &lt;em&gt;Interfacer.&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;External interfacer (gateway):&lt;/strong&gt; To cross external object neighborhoods (as is the case when we send messages out to remote APIs or to libraries which we don’t own), the more common name for the object that encapsulates this access is called a &lt;em&gt;Gateway&lt;/em&gt;, however — stereotypically, it’s an &lt;em&gt;Interfacer&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UI-related interfacers:&lt;/strong&gt; &lt;em&gt;Interfacers&lt;/em&gt; which listen to events from the UI and pass them to non-UI related parts of our applications are typically just called &lt;em&gt;Event Listeners&lt;/em&gt; (in JavaScript, there is an &lt;em&gt;EventListener API&lt;/em&gt;) whereas objects that format data for presentation in the UI are aptly named &lt;em&gt;Presenters&lt;/em&gt;. Both are stereotypical &lt;em&gt;Interfacers&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/design/object-stereotypes/Interfacer.svg&quot; alt=&quot;Interfacer.svg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Considerations-on-stereotypes&quot; style=&quot;position:relative;&quot;&gt;Considerations on stereotypes&lt;a href=&quot;#Considerations-on-stereotypes&quot; aria-label=&quot;Considerations on stereotypes permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Stereotypes make it easier for us to identify objects&lt;/strong&gt;: This should clear up a lot of headroom for you. Because we know the six general types of objects we’re likely to encounter, we&apos;ll find it easier to invent object candidates. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stereotypes help us emphasize what matters about our objects:&lt;/strong&gt; We’re constantly striving to ensure that our objects are cohesive and well-defined. If we discover a new object candidate, we can ask ourselves “what stereotype is this most like?” This question helps us determine if we should redistribute misplaced responsibilities to other object candidates to make them more cohesive and focused.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A candidate object can belong to more than one stereotype&lt;/strong&gt;: Taking it the other direction, there are times when objects have responsibilities that float between multiple stereotypes. For example, consider the &lt;em&gt;Repository&lt;/em&gt; pattern. If it were to also cache the objects it retrieves, we’d say it acts more like a combination of the &lt;em&gt;Interfacer&lt;/em&gt; and &lt;em&gt;Structurer&lt;/em&gt; stereotypes. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Object stereotypes make understanding &amp;#x26; communication simpler&lt;/strong&gt;: It’s easier to talk about design with stereotypes in mind. Once you’re aware of object stereotypes, you’ll start seeing them (or the lack of them) in the frameworks and libraries you’re using. This presents a great opportunity for us to get what we need by creating it ourselves.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[98% of Developers Use React as a Framework, Not a Library]]></title><description><![CDATA[What’s the difference between a framework and a library? A framework is something that you plug your code into. A library is something that…]]></description><link>https://khalilstemmler.com/blogs/frontend/using-react-as-a-framework/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/frontend/using-react-as-a-framework/</guid><pubDate>Sun, 04 Sep 2022 15:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;🌱 Note:&lt;/b&gt; This post is still being updated for clarity and utility. Short on time this week.&lt;/p&gt;
&lt;p&gt;What’s the difference between a framework and a library?&lt;/p&gt;
&lt;p&gt;A framework is something that you plug &lt;em&gt;your code into&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A library is something that you plug &lt;em&gt;into your code&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If that’s the case, then 98% of developers use React as a framework instead of a library.&lt;/p&gt;
&lt;h2 id=&quot;Control-centers&quot; style=&quot;position:relative;&quot;&gt;Control centers&lt;a href=&quot;#Control-centers&quot; aria-label=&quot;Control centers permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://khalilstemmler.com/articles/object-oriented/design/responsibility-driven-design/&quot;&gt;Responsibility-Driven Design&lt;/a&gt;, there’s this idea of control centers. &lt;/p&gt;
&lt;p&gt;Control centers are the parts of your codebase tasked with &lt;em&gt;coordination&lt;/em&gt; and &lt;em&gt;control&lt;/em&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Coordination = handling events, reacting to them, relaying events to others&lt;/li&gt;
&lt;li&gt;Control = directing the action of lower-level objects, delegating work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every application has at least one place that does &lt;em&gt;coordination&lt;/em&gt; and often several places that handle &lt;em&gt;control&lt;/em&gt; (hence why we tend to have multiple controllers in MVC).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/frontend/Untitled.svg&quot; alt=&quot;Untitled&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Most-developers-let-React-handle-coordination-and-control&quot; style=&quot;position:relative;&quot;&gt;Most developers let React handle coordination and control&lt;a href=&quot;#Most-developers-let-React-handle-coordination-and-control&quot; aria-label=&quot;Most developers let React handle coordination and control permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The React documentation and thought leadership today urges you to write the majority of your code &lt;em&gt;within&lt;/em&gt; React, using custom Hooks as the key place to put things that have to do with control, data, rules, processes, and so on. &lt;/p&gt;
&lt;p&gt;This is great for getting started, but essentially, we’re doing the exact same thing we try to avoid doing on the backend: creating an &lt;a href=&quot;https://khalilstemmler.com/wiki/anemic-domain-model/&quot;&gt;anemic domain model&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Coordination-and-control-are-application-layer-concerns&quot; style=&quot;position:relative;&quot;&gt;Coordination and control are application layer concerns&lt;a href=&quot;#Coordination-and-control-are-application-layer-concerns&quot; aria-label=&quot;Coordination and control are application layer concerns permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Just like application service use cases and command handlers are application layer concerns in backend programming, on the frontend, code that determines what happens after a click or a keypress - these too, are application layer concerns.&lt;/p&gt;
&lt;h3 id=&quot;What-happens-when-we-put-coordination-and-control-inside-of-React&quot; style=&quot;position:relative;&quot;&gt;What happens when we put coordination and control inside of React?&lt;a href=&quot;#What-happens-when-we-put-coordination-and-control-inside-of-React&quot; aria-label=&quot;What happens when we put coordination and control inside of React permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I can think of a few different implications, but the key one is that we have &lt;strong&gt;less testing options&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Because you need React to spin up and test your application (and domain) layer code, the idea of testing your core functionality in isolation isn’t possible. In fact, it&apos;s borderline impossible. &lt;/p&gt;
&lt;h3 id=&quot;How-do-we-fix-this&quot; style=&quot;position:relative;&quot;&gt;How do we fix this?&lt;a href=&quot;#How-do-we-fix-this&quot; aria-label=&quot;How do we fix this permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Decouple from the library and framework&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create your own control center&lt;/strong&gt; — To create your own control center, you need at least one &lt;em&gt;Coordinator&lt;/em&gt; and as many &lt;em&gt;Controllers&lt;/em&gt; as necessary (these are synonymous to application-layer &lt;em&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;Use Cases&lt;/a&gt;&lt;/em&gt; though I’ve also used the word &lt;em&gt;Interactor&lt;/em&gt; and describe the type of logic they encapsulate as &lt;a href=&quot;https://khalilstemmler.com/articles/client-side-architecture/layers/#Interaction-layer&quot;&gt;Interaction Logic&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will say more on exactly how to do this in another post, but for now, see the following Object Stereotypes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Coordinator:&lt;/strong&gt; &lt;em&gt;Coordinators&lt;/em&gt; are one of two objects most responsible for determining how control works in our applications. The &lt;em&gt;Coordinator&lt;/em&gt; stereotype has one real purpose: to pass information to other objects so that they can do work. This is effectively the &lt;em&gt;Observer Pattern.&lt;/em&gt; While it’s common practice to use something like Redux to create this, it’s not necessary. You can have something like this working in less than 20 lines of code.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/frontend/Coordinator.svg&quot; alt=&quot;Coordinator.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Controller&lt;/strong&gt;: In RDD, the &lt;em&gt;Controller&lt;/em&gt; stereotype behaves the same way as the &lt;em&gt;Use Case&lt;/em&gt; pattern. The stereotypical responsibility held by a &lt;em&gt;Controller&lt;/em&gt; is to act as a higher-level (&lt;em&gt;application&lt;/em&gt;-layer specifically), declaratively focused object that coordinates the behaviour of lower-level concerns. The &lt;em&gt;Controller&lt;/em&gt; pulls other objects together and makes them collaborate with each other. They can be modelled as &lt;a href=&quot;https://wiki.solidbook.io/13-Features-(use-cases)-are-the-key-193ca4bbb8604c0eada33d1ac86ed517&quot;&gt;Features&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/frontend/Controller.svg&quot; alt=&quot;Controller.svg&quot;&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[No title]]></title><link>https://khalilstemmler.com/wiki/responsibility-driven design/contract/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/responsibility-driven design/contract/</guid><pubDate>Thu, 04 Aug 2022 04:05:26 GMT</pubDate><content:encoded></content:encoded></item><item><title><![CDATA[No title]]></title><link>https://khalilstemmler.com/wiki/responsibility-driven design/collaboration/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/responsibility-driven design/collaboration/</guid><pubDate>Thu, 04 Aug 2022 04:05:26 GMT</pubDate><content:encoded></content:encoded></item><item><title><![CDATA[No title]]></title><link>https://khalilstemmler.com/wiki/responsibility-driven design/responsibility/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/responsibility-driven design/responsibility/</guid><pubDate>Thu, 04 Aug 2022 04:05:26 GMT</pubDate><content:encoded></content:encoded></item><item><title><![CDATA[No title]]></title><link>https://khalilstemmler.com/wiki/responsibility-driven design/role/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/responsibility-driven design/role/</guid><pubDate>Thu, 04 Aug 2022 04:05:26 GMT</pubDate><content:encoded></content:encoded></item><item><title><![CDATA[What Is Hashing?]]></title><description><![CDATA[Hashing is a technique used to convert a key into another value (typically for cryptographic or data storage purposes). It works by running…]]></description><link>https://khalilstemmler.com/blogs/data-structures-algorithms/what-is-hashing/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/data-structures-algorithms/what-is-hashing/</guid><pubDate>Tue, 10 May 2022 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Hashing is a technique used to convert a key into another value (typically for cryptographic or data storage purposes). It works by running a mathematical function (called a hash function) called a key to create a new value — the hash (or the hash value).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/data-structures/what-is-hashing/hash-function.png&quot; alt=&quot;hash-function.png&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;One-way-hashes&quot; style=&quot;position:relative;&quot;&gt;One-way hashes&lt;a href=&quot;#One-way-hashes&quot; aria-label=&quot;One way hashes permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Cryptographically secure hash functions are said to be good when they’re one way (one way hashes). This means that you cannot get the original key from the hash value.&lt;/p&gt;
&lt;h2 id=&quot;Collisions&quot; style=&quot;position:relative;&quot;&gt;Collisions&lt;a href=&quot;#Collisions&quot; aria-label=&quot;Collisions permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If a hash function yields the same hash value for two or more keys, then that’s when we end up with a collision — this is non-ideal. There are ways to handle this (&lt;a href=&quot;https://khalilstemmler.com/blogs/data-structures-algorithms/hash-tables/#Collisions&quot;&gt;see this article&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&quot;When-we-do-we-hashing&quot; style=&quot;position:relative;&quot;&gt;When we do we hashing?&lt;a href=&quot;#When-we-do-we-hashing&quot; aria-label=&quot;When we do we hashing permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Implementing-hash-tables&quot; style=&quot;position:relative;&quot;&gt;Implementing hash tables&lt;a href=&quot;#Implementing-hash-tables&quot; aria-label=&quot;Implementing hash tables permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://khalilstemmler.com/blogs/data-structures-algorithms/hash-tables/&quot;&gt;Hash tables&lt;/a&gt; are a data structure that helps us store key/value data. They are comprised of two parts — a storage structure (be it an array, object, etc) and a hash function.&lt;/p&gt;
&lt;p&gt;The hash function is responsible for fitting data within the data structure so that it can be retrieved later. &lt;/p&gt;
&lt;p&gt;If the storage is bounded (fixed) such as an array, then the hash function must generate a key which can be used as the index, but fits within the size constraints of the array.&lt;/p&gt;
&lt;p&gt;For example, a trivial formula to compute the index of a string or integer key is to do:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; key &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; sizeOfTable&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This would work, but for any fixed size table, we’re likely to run into collisions eventually.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;See here for “&lt;a href=&quot;https://khalilstemmler.com/blogs/data-structures-algorithms/hash-tables/#Collision-detection-and-dynamic-array-resizing&quot;&gt;Collision detection and dynamic array resizing&lt;/a&gt;&quot;.&lt;/p&gt;
&lt;p&gt;When storage is &lt;em&gt;unbounded&lt;/em&gt; — like when using a JavaScript object — we don’t have to worry about collisions. We can just use some unique aspect of the data (such as an email address, phone number, or a compound-key) to create the hash value to use as an index.&lt;/p&gt;
&lt;p&gt;However, if security is important, we should still use a cryptographic function to create the hash.&lt;/p&gt;
&lt;p&gt;That leads to the final point.&lt;/p&gt;
&lt;h3 id=&quot;Cryptography--data-encryption&quot; style=&quot;position:relative;&quot;&gt;Cryptography &amp;#x26; data encryption&lt;a href=&quot;#Cryptography--data-encryption&quot; aria-label=&quot;Cryptography  data encryption permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Hashing is a very common technique when it comes to cryptography. The most common reason we hash is to convert passwords to something more secure (than plain text) before we store them to a database. We do this for two reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If a hacker steals the records from the db, they don’t get the actual passwords — just the hashed ones (which cannot be reversed since they were one way hashes).&lt;/li&gt;
&lt;li&gt;To prevent staff from accidentally viewing plain-text passwords in the production database. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To hash passwords, check out &lt;a href=&quot;https://www.npmjs.com/package/md5&quot;&gt;MD5&lt;/a&gt; or SHA-2 — two widely-used crypto hashes.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Non-Functional Requirements (with Examples)]]></title><description><![CDATA[What’s the difference between software that works and software that works well? Non-functional requirements. Consider the following example…]]></description><link>https://khalilstemmler.com/articles/object-oriented/analysis/non-functional-requirements/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/object-oriented/analysis/non-functional-requirements/</guid><pubDate>Tue, 03 May 2022 22:04:10 GMT</pubDate><content:encoded>&lt;p&gt;What’s the difference between software that works and software that works &lt;em&gt;well&lt;/em&gt;? Non-functional requirements.&lt;/p&gt;
&lt;p&gt;Consider the following example.&lt;/p&gt;
&lt;p&gt;We’ve been hired to build an online store for a local brick-and-mortar store. We’ve gone ahead and applied the &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/feature-driven/&quot;&gt;feature/use case-driven approach&lt;/a&gt; to design popularized by XP. We’ve done that process of identifying the use cases, planning and estimating them with user stories, and thinking about how we can write those stories as tests &lt;a href=&quot;https://twitter.com/khalilstemmler/status/1494719618451136512&quot;&gt;with BDD&lt;/a&gt;. Looking back at what we’ve done, we’ve &lt;a href=&quot;https://wiki.solidbook.io/22-Acceptance-Tests-7bf96fa035694e329455c11c740ab9a7/&quot;&gt;acceptance tested&lt;/a&gt; the &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt;, integration tested the infrastructure code that interacts with external APIs and the outside world, and even did a little bit of end-to-end testing to ensure things work from front to back. &lt;/p&gt;
&lt;p&gt;Great job! &lt;/p&gt;
&lt;p&gt;Unfortunately, upon going live, we’re surprised hear about a myriad of complaints from the customer. &lt;/p&gt;
&lt;p&gt;The customer calls us and says:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“The cart page takes around 10 seconds to load — it’s way too slow! If it’s already this slow under regular traffic, I’m not sure what’s going to happen when we have our boxing day sale. Will the site just go down completely?”&lt;/li&gt;
&lt;li&gt;“We keep having to refund orders! Customers are purchasing products that are out of stock, so I’m not sure how you did the sync to our backend inventory but it’s either taking too long to sync or it’s not syncing at all.”&lt;/li&gt;
&lt;li&gt;“The site looks weird on mobile.”&lt;/li&gt;
&lt;li&gt;“Customers are confused about how to get to the page where they can see the status of their orders.”&lt;/li&gt;
&lt;li&gt;“The animations moving between pages feels kind of choppy. I was expecting it to be smoother. Can you fix that?”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dang. Where did we go wrong? &lt;/p&gt;
&lt;p&gt;Well, behind each of these disgruntlements lies a missed requirement — a &lt;strong&gt;non-functional requirement&lt;/strong&gt;. And non-functional requirements are an incredibly important piece of the puzzle that is software design.&lt;/p&gt;
&lt;h3 id=&quot;What-well-learn&quot; style=&quot;position:relative;&quot;&gt;What we’ll learn&lt;a href=&quot;#What-well-learn&quot; aria-label=&quot;What well learn permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In this post, we’re going to discuss:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What non-functional requirements are and why knowing them can help us better design systems that meets the needs of the customer and end users.&lt;/li&gt;
&lt;li&gt;How non-functional requirements compare to functional ones.&lt;/li&gt;
&lt;li&gt;Best practices to handle non-functional requirements.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;What-is-a-non-functional-requirement&quot; style=&quot;position:relative;&quot;&gt;What is a non-functional requirement?&lt;a href=&quot;#What-is-a-non-functional-requirement&quot; aria-label=&quot;What is a non functional requirement permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Where functional requirements describe what the system should do (ie: the use cases or features), &lt;strong&gt;non-functional requirements (sometimes called constraints or behavioural requirements) describe &lt;em&gt;what the system should be&lt;/em&gt; (ie: the system level properties).&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;With functional requirements, if we’re following the &lt;a href=&quot;https://wiki.solidbook.io/6-Organizing-things-d70980d25a424987b1399382417d5944&quot;&gt;feature-driven folder structure&lt;/a&gt;, it can be relatively easy to trace features down to individual &lt;a href=&quot;https://khalilstemmler.com/articles/client-side-architecture/principles/#Features-are-vertical-slices&quot;&gt;slices&lt;/a&gt; of functionality or modules within our application.&lt;/p&gt;
&lt;p&gt;Non-functional requirements, however — these are system-level properties. Since they describe the system as a whole it’s a lot harder (and sometimes impossible) to trace them down to a location in the codebase.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/analysis/non-functional-requirements/functional-vs-non-functional-requirements.png&quot; alt=&quot;Functional vs. non-functional requirements&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Types-of-non-functional-requirements&quot; style=&quot;position:relative;&quot;&gt;Types of non-functional requirements&lt;a href=&quot;#Types-of-non-functional-requirements&quot; aria-label=&quot;Types of non functional requirements permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There’s no one single definitive list of &lt;em&gt;valid&lt;/em&gt; non-functional requirements. Some of them can also been seen as related or within umbrellas of each other (for example: we can define &lt;em&gt;Performance&lt;/em&gt; or &lt;em&gt;Speed&lt;/em&gt; as NFRs within &lt;em&gt;Efficiency&lt;/em&gt;). &lt;/p&gt;
&lt;p&gt;To get us started, here’s a short list. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Capacity — How much data can we store? Will we ever run out of storage space?&lt;/li&gt;
&lt;li&gt;Regulatory — Do local, regional, provincial or state laws or regulations that dictate some aspect of what we’re legally allowed to do?&lt;/li&gt;
&lt;li&gt;Portability — Which browsers, operating systems and versions should we expect the software to work on? Is it cross-platform?&lt;/li&gt;
&lt;li&gt;Reliability — How often can we expect the system to be available to use? How does it handle critical failures? How long does it take for a system to come back online after a failure?&lt;/li&gt;
&lt;li&gt;Performance — How fast should requests process? How many requests can we handle at any given time? What should we expect for response times when the system is under heavy load?&lt;/li&gt;
&lt;li&gt;Localization — Will the system adapt to measurement systems, timezones, and other locally specific concepts in other states or provinces?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Non-functional-requirement-examples&quot; style=&quot;position:relative;&quot;&gt;Non-functional requirement examples&lt;a href=&quot;#Non-functional-requirement-examples&quot; aria-label=&quot;Non functional requirement examples permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Lets say that a functional requirement in a trading application was to make sure that when users execute the &lt;code class=&quot;language-text&quot;&gt;getOffers&lt;/code&gt; use case, they’re presented with a list of offers, then a larger-picture non-functional requirement may state:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Scalability, performance, efficiency:&lt;/strong&gt; “The website should process each request within 4 seconds or less 99% of the time.”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scalability, performance:&lt;/strong&gt; “In standard network conditions, the website should fully load in less than 5 seconds when the total number of simultaneous users on the website are greater than 50,000.”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security, data integrity, capacity:&lt;/strong&gt; “Every unauthorized request to a resource must be logged and stored for audit over the next 5 years.”&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Execution-vs-evolution-qualities&quot; style=&quot;position:relative;&quot;&gt;Execution vs. evolution qualities&lt;a href=&quot;#Execution-vs-evolution-qualities&quot; aria-label=&quot;Execution vs evolution qualities permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Because there are so many different non-functional requirements out there, a great way to think about them is to consider them to be either either &lt;em&gt;execution qualities&lt;/em&gt; or &lt;em&gt;evolution qualities&lt;/em&gt;. Allow me to explain the difference.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Execution qualities&lt;/strong&gt;: These are aspects which can only be observed at runtime such as security, usability, and efficiency (performance, speed).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Evolution qualities&lt;/strong&gt;: These are aspects that have to do with how it affects our ability to evolve the code and structure over time such as if the code is testable, flexible, maintainable, and scalable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/analysis/non-functional-requirements/non-functional-requirements-map.png&quot; alt=&quot;Non-functional requirements map&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;Functional-vs-non-functional-requirements&quot; style=&quot;position:relative;&quot;&gt;Functional vs. non-functional requirements&lt;a href=&quot;#Functional-vs-non-functional-requirements&quot; aria-label=&quot;Functional vs non functional requirements permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let’s make sure we really understand the differences between the two.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Functional&lt;/th&gt;
&lt;th&gt;Non-functional requirement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Description&lt;/td&gt;
&lt;td&gt;Describes what the system should do&lt;/td&gt;
&lt;td&gt;Constrains the functional requirements and describes “how the system should be”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mandatory&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No, but some are more important than others&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scope&lt;/td&gt;
&lt;td&gt;As a use case / feature - component level&lt;/td&gt;
&lt;td&gt;As a system-level property against the system as a whole&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ease of definition&lt;/td&gt;
&lt;td&gt;Straightforward&lt;/td&gt;
&lt;td&gt;More difficult (it can be difficult to make qualitative properties quantitative — we sometimes have to use indicators instead).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test types&lt;/td&gt;
&lt;td&gt;Unit, integration, acceptance, end-to-end tests&lt;/td&gt;
&lt;td&gt;Performance, stress, security, usability testing (for example)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Example&lt;/td&gt;
&lt;td&gt;Given a user has not created an account, when they register, a new users should be created and an email should be sent to them.&lt;/td&gt;
&lt;td&gt;(1) The site should be able to process 99.9% of requests in less than 6 seconds. (2) Emails should be sent no later than 20 minutes after the triggering event.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;Why-should-we-learn-about-non-functional-requirements&quot; style=&quot;position:relative;&quot;&gt;Why should we learn about non-functional requirements&lt;a href=&quot;#Why-should-we-learn-about-non-functional-requirements&quot; aria-label=&quot;Why should we learn about non functional requirements permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My first startup project was used by few hundreds users. It wasn’t until it received a &lt;a href=&quot;https://www.blogto.com/tech/2018/04/students-jobs-toronto/&quot;&gt;moderate amount of press&lt;/a&gt; on a popular website that I learned it was &lt;em&gt;not&lt;/em&gt; cut out for real-world production traffic. With thousands of people signing up at the same time, the website — hosted on a tiny AWS EC2 micro instance, unable to stand up to the &lt;strong&gt;performance, efficiency, and reliability non-functional requirements&lt;/strong&gt; — died a tragic death and left many users annoyed... never to return again.&lt;/p&gt;
&lt;h3 id=&quot;Its-one-of-the-main-reasons-why-projects-fail&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;It’s one of the main reasons why projects fail&lt;/strong&gt;&lt;a href=&quot;#Its-one-of-the-main-reasons-why-projects-fail&quot; aria-label=&quot;Its one of the main reasons why projects fail permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Often times, even if we get all the features working, non-functional requirements are the key factor that dictate if a project will succeed or fail. It’s taken me some time to realize this, but it’s very much true.&lt;/p&gt;
&lt;p&gt;What good is a slow social networking website? Who’s going to play a game that crashes all the time? Is the project really a success if it’s written without tests and every time we add or change a feature, we fear breaking an existing feature in a distant module? What if people don’t even know how to use it?&lt;/p&gt;
&lt;h3 id=&quot;It-has-a-massive-influence-on-architecture-execution-qualities&quot; style=&quot;position:relative;&quot;&gt;It has a massive influence on architecture (execution qualities)&lt;a href=&quot;#It-has-a-massive-influence-on-architecture-execution-qualities&quot; aria-label=&quot;It has a massive influence on architecture execution qualities permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Non-functional requirements provide hints to what sorts of &lt;em&gt;architectural components (like queues and caches)&lt;/em&gt; and &lt;em&gt;patterns (design patterns and architectural patterns)&lt;/em&gt; we’ll need in order to successfully get the system to &lt;em&gt;be&lt;/em&gt; a certain way — to have the design criteria we need.&lt;/p&gt;
&lt;p&gt;For example, a media-heavy site like Instagram or YouTube allows users to upload media. That’s the functional requirement. Non-functionally though, we’d like to afford users the capability to continue to move around the site while their media is being uploaded. &lt;/p&gt;
&lt;p&gt;This simple &lt;strong&gt;usability&lt;/strong&gt; non-functional requirement introduces the need for some component capable of decoupling the user-facing command of &lt;code class=&quot;language-text&quot;&gt;UploadMedia&lt;/code&gt; from the work to be done (such as processing the media, encoding it, annotating it, adding subtitles, etc). Therefore, it’s likely we’d benefit from an event-based architecture and the addition of a &lt;em&gt;Job/Task Queue&lt;/em&gt; as an important architectural component. &lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Filling in the non-functional gaps with Object Design&lt;/b&gt;: Do I just automatically &lt;i&gt;know&lt;/i&gt; what sorts of components we need? While a familiarity of patterns, tools, and services and the sorts of problems they solve helps, there &lt;i&gt;is&lt;/i&gt; a structured design method to discover what sorts of components need to either be invented or integrated into our application architecture. It’s called &lt;i&gt;Object Design&lt;/i&gt; (or as I like to say &lt;i&gt;how to do object-oriented programming properly&lt;/i&gt;). Object design teaches us how to discover and divvy up the necessary requirements (both functional and non-functional requirements) into neighbourhoods of collaborating objects. In Part V — Object Design with Tests from &lt;a href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt;, we learn &lt;a href=&quot;https://khalilstemmler.com/articles/object-oriented/design/responsibility-driven-design/&quot;&gt;Responsibility-Driven Design&lt;/a&gt; and foundational skills for system design.&lt;/p&gt;
&lt;h3 id=&quot;Makes-good-design-techniques-necessary-evolution-qualities&quot; style=&quot;position:relative;&quot;&gt;Makes good design techniques necessary (evolution qualities)&lt;a href=&quot;#Makes-good-design-techniques-necessary-evolution-qualities&quot; aria-label=&quot;Makes good design techniques necessary evolution qualities permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A large reason why we use things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tests (acceptance, E2E, integration, unit)&lt;/li&gt;
&lt;li&gt;Design patterns&lt;/li&gt;
&lt;li&gt;Design principles&lt;/li&gt;
&lt;li&gt;Architectural styles&lt;/li&gt;
&lt;li&gt;Architectural patterns&lt;/li&gt;
&lt;li&gt;Domain-driven design&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;... is because they lead to more testable, flexible, and maintainable code. The &lt;strong&gt;evolution qualities&lt;/strong&gt;. That’s pretty much the goal for us web developers focused on taming backend complexity. As a result, following the many good coding practices listed above leads to code can that can be more easily evolved, lives longer, is more understandable, and so on. &lt;/p&gt;
&lt;h2 id=&quot;Best-practices-for-dealing-with-non-functional-requirements&quot; style=&quot;position:relative;&quot;&gt;Best practices for dealing with non-functional requirements&lt;a href=&quot;#Best-practices-for-dealing-with-non-functional-requirements&quot; aria-label=&quot;Best practices for dealing with non functional requirements permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Uncover non-functional requirements early&lt;/strong&gt;: Because of the impact NFRs have on architecture, it’s important to discover them early. Once you know the functional requirements, ask the customer (or yourself) probing questions to determine what non-functional requirements exist to constrain the functional ones. How fast should it be? How do users expect this to behave? What will happen if users have a lot of data in their account? Are there auditing requirements? What could make this project fail? What does affordability look like for you? How easy will it be to change? Can we expect users to know what to do?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Make requirements as measurable as possible:&lt;/strong&gt; Here’s an example of a non-functional requirement that you can’t really test or measure: “it should be fast as hell”. What if we made that quantitative and said “it should respond to 95% of requests within 3 seconds”? That’s better, isn’t it?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use popular products as a quality baseline:&lt;/strong&gt; Every couple of years, users come to expect better website experiences. Faster, more real-time, more of that &lt;em&gt;wow-factor&lt;/em&gt; and so on. To get a baseline for the non-functional requirements, ask customers to tell you what they like from other websites. It could be just that it &lt;em&gt;feels consistent&lt;/em&gt; or has a lot of whitespace. These are all constraints on the functional requirements.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Summary&quot; style=&quot;position:relative;&quot;&gt;Summary&lt;a href=&quot;#Summary&quot; aria-label=&quot;Summary permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Non-functional requirements describe what the system &lt;em&gt;should be&lt;/em&gt; instead of what the system should &lt;em&gt;do&lt;/em&gt;. It’s about system-level properties.&lt;/li&gt;
&lt;li&gt;Non-functional requirements can be divided into two rough categories: execution qualities and evolution qualities.&lt;/li&gt;
&lt;li&gt;We should learn non-functional requirements because failing to meet them is one of the main reasons why projects fail, they have a massive influence on architecture, and they make a solid case for good coding practices like TDD and DDD and more advanced concepts like design patterns and architectural styles.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Further-reading&quot; style=&quot;position:relative;&quot;&gt;Further reading&lt;a href=&quot;#Further-reading&quot; aria-label=&quot;Further reading permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;From-Non-Functional-Requirements-to-Design-through-Patterns&quot; style=&quot;position:relative;&quot;&gt;From Non-Functional Requirements to Design through Patterns&lt;a href=&quot;#From-Non-Functional-Requirements-to-Design-through-Patterns&quot; aria-label=&quot;From Non Functional Requirements to Design through Patterns permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There&apos;s a research paper I&apos;m currently in the middle of reading for the upcoming section in &lt;a href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt; titled &quot;Part V: Object-Oriented Design (with Tests)&quot; -- it&apos;s called &quot;&lt;a href=&quot;https://www.researchgate.net/publication/2396162_From_Non-Functional_Requirements_to_Design_through_Patterns&quot;&gt;From Non-Function Requirements to Design through Patterns&lt;/a&gt;&quot; by Eric Yu and Daniel Gross from my neighboring University of Toronto. &lt;/p&gt;
&lt;p&gt;In the paper, they state that design patterns are excellent tools for handling particular NFRs even though they often come with tradeoffs. The paper presents three design patterns and shows how they can be used to solve some NFRs. &lt;/p&gt;
&lt;p&gt;We&apos;ve known this to be true. Just look at Redux: the front-end state management library centered around the Observer Pattern. What properties would a system architected around the observer pattern gain? Consistency, accuracy, generality, expandability, traceability, and more! We tend to like the elegance of this decoupled publish-subscribe pattern for so many reasons. It makes logging, auditing, tracking events, and so on easier. In fact, if we zoom out and think about &lt;a href=&quot;https://khalilstemmler.com/articles/oop-design-principles/command-query-separation/&quot;&gt;CQRS&lt;/a&gt; and the fact that we use &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/chain-business-logic-domain-events/&quot;&gt;Domain Events&lt;/a&gt; in a Hexagonal Architecture, you will &lt;em&gt;also&lt;/em&gt; see the Observer Pattern - but at an architectural level!&lt;/p&gt;
&lt;h3 id=&quot;An-Object-Oriented-Architecture-from-Part-III-Phronesis&quot; style=&quot;position:relative;&quot;&gt;An Object-Oriented Architecture from Part III: Phronesis&lt;a href=&quot;#An-Object-Oriented-Architecture-from-Part-III-Phronesis&quot; aria-label=&quot;An Object Oriented Architecture from Part III Phronesis permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you&apos;re a regular reader of this blog, you&apos;re passionate or curious about how to design systems in a testable, flexible, maintainable way. In &quot;&lt;a href=&quot;https://wiki.solidbook.io/24-An-Object-Oriented-Architecture-fc5ef2681c054be2ae628318de0c4cfa&quot;&gt;Chapter 24. An Object-Oriented Architecture&lt;/a&gt;&quot; from solidbook.io, we delve into a common object-oriented architecture that works for most web developers.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Architecture is meant to support the functional and non-functional requirements. A good architecture is one that does this. In object-oriented web or business applications, perhaps one of the most important non-functional requirements is the ability to &lt;em&gt;test&lt;/em&gt; business logic complexity effectively. I argue that a layered architecture is the superior technique. Why? It lets us implement functional requirements in a test-first and domain-driven way.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;References&quot; style=&quot;position:relative;&quot;&gt;References&lt;a href=&quot;#References&quot; aria-label=&quot;References permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cs.toronto.edu/~sme/CSC340F/slides/16-NFRs.pdf&quot;&gt;University of Toronto — Non-Functional Requirements Lecture by Steve Easterbrook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.fintechna.com/articles/non-functional-requirements-specification-framework-for-corebanking-transformation-to-cloud/&quot;&gt;https://www.fintechna.com/articles/non-functional-requirements-specification-framework-for-corebanking-transformation-to-cloud/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[JavaScript forEach | Looping Through an Array in JS]]></title><description><![CDATA[For many developers, JavaScript acts as introduction to the functional programming paradigm. And if you've never encountered callback…]]></description><link>https://khalilstemmler.com/blogs/javascript/for-each/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/javascript/for-each/</guid><pubDate>Tue, 03 May 2022 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;For many developers, JavaScript acts as introduction to the functional programming paradigm. And if you&apos;ve never encountered &lt;em&gt;callback functions&lt;/em&gt; before, the JavaScript for each function might look a little funny. &lt;/p&gt;
&lt;p&gt;In this quick article, we&apos;re going to see how to iterate over an array of data using JavaScript&apos;s forEach function. We&apos;ll look at different ways to call it and discuss when to use it vs. the traditional for loop.&lt;/p&gt;
&lt;h2 id=&quot;Using-the-JavaScript-for-each-function&quot; style=&quot;position:relative;&quot;&gt;Using the JavaScript for each function&lt;a href=&quot;#Using-the-JavaScript-for-each-function&quot; aria-label=&quot;Using the JavaScript for each function permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In JavaScript, the array object contains a &lt;code class=&quot;language-text&quot;&gt;forEach&lt;/code&gt; method. This means that on any array, we can call &lt;code class=&quot;language-text&quot;&gt;forEach&lt;/code&gt; like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; fruits &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;apples&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;oranges&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;bananas&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

fruits&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This should print out the following.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;apples &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
oranges &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
bananas &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let&apos;s explain how this works.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We pass an &lt;em&gt;anonymous function&lt;/em&gt; to the &lt;code class=&quot;language-text&quot;&gt;forEach&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;Within that anonymous function, we include parameters to get access to the current &lt;code class=&quot;language-text&quot;&gt;item&lt;/code&gt; and the numerical &lt;code class=&quot;language-text&quot;&gt;index&lt;/code&gt; in the array that the item represents.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The function we provide to the &lt;code class=&quot;language-text&quot;&gt;forEach&lt;/code&gt; function has three parameters (two of which are optional).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;(Required) The current element - Represents the current element&lt;/li&gt;
&lt;li&gt;(Optional) Index - Returns the current index &lt;/li&gt;
&lt;li&gt;(Optional) Array - Returns the entire array for each loop&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Alternate-ways-to-call-it&quot; style=&quot;position:relative;&quot;&gt;Alternate ways to call it&lt;a href=&quot;#Alternate-ways-to-call-it&quot; aria-label=&quot;Alternate ways to call it permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Option-1-An-anonymous-function&quot; style=&quot;position:relative;&quot;&gt;Option 1: An anonymous function&lt;a href=&quot;#Option-1-An-anonymous-function&quot; aria-label=&quot;Option 1 An anonymous function permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The first of the alternate way to call this function is to utilize the anonymous function. This is what we just saw.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Anonymous function&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Write what you&apos;d like to happen here&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Option-2-Using-arrow-functions&quot; style=&quot;position:relative;&quot;&gt;Option 2: Using arrow functions&lt;a href=&quot;#Option-2-Using-arrow-functions&quot; aria-label=&quot;Option 2 Using arrow functions permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The second option is to utilize an arrow function.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Try this out. It allows you to write the loop on a single line.&lt;/p&gt;
&lt;h3 id=&quot;Option-3-A-callback-function&quot; style=&quot;position:relative;&quot;&gt;Option 3: A callback function&lt;a href=&quot;#Option-3-A-callback-function&quot; aria-label=&quot;Option 3 A callback function permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The last option is to utilize a callback function, which is really just a function defined separately that we pass in as an argument to the &lt;code class=&quot;language-text&quot;&gt;forEach&lt;/code&gt; function.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; fruits &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;apples&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;oranges&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;bananas&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;printPretty&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;index&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; - &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;item&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

fruits&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;printPretty&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This should print out the following:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; - apples
&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; - oranges
&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; - bananas&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;When-to-use-the-for-loop-vs-a-for-loop&quot; style=&quot;position:relative;&quot;&gt;When to use the for loop vs. a for loop&lt;a href=&quot;#When-to-use-the-for-loop-vs-a-for-loop&quot; aria-label=&quot;When to use the for loop vs a for loop permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most of us first learn about loops the traditional way - you know, the loops with counters that get incremented? Like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; fruits &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;apples&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;oranges&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;bananas&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; fruits&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fruits&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The truth is, you can use either traditional for loops or &lt;code class=&quot;language-text&quot;&gt;forEach&lt;/code&gt; loops. It doesn&apos;t matter. &lt;/p&gt;
&lt;p&gt;However, using &lt;code class=&quot;language-text&quot;&gt;forEach&lt;/code&gt; loops results in code that looks a lot more &lt;strong&gt;declarative&lt;/strong&gt; and easy to read, especially if you&apos;re dealing with nested loops (which I opt to try to avoid in the first place).&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Responsibility-Driven Design]]></title><description><![CDATA[“Understanding responsibilities is key to good object-oriented design” — Martin Fowler Do you struggle with object-oriented programming…]]></description><link>https://khalilstemmler.com/articles/object-oriented/design/responsibility-driven-design/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/object-oriented/design/responsibility-driven-design/</guid><pubDate>Sat, 16 Apr 2022 22:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;special-quote&quot;&gt;🌱 This blog post hasn&apos;t fully bloomed. It&apos;s very likely to change over the next little while.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Understanding responsibilities is key to good object-oriented design” — Martin Fowler&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Do you struggle with object-oriented programming? Does it sometimes feel like it&apos;s overly complex for no reason? When you&apos;re writing object-oriented code, do you sometimes feel like you&apos;re slowly watching it turn into a spaghetti mess? Do you sometimes feel confused as to when you should create new classes? Do you feel like it might be better to &lt;em&gt;just use functions&lt;/em&gt; instead? &lt;/p&gt;
&lt;p&gt;What if I told you that there&apos;s more to building software with objects than just classes, &lt;a href=&quot;/articles/object-oriented/programming/4-principles/&quot;&gt;inheritance, polymorphism and encapsulation&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;What if I told you that there&apos;s a &lt;em&gt;design method&lt;/em&gt; - a way of turning requirements into object-oriented designs - that &lt;em&gt;actually&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;And what if I told you that it was &lt;strong&gt;the programming world&apos;s most influentual design method&lt;/strong&gt; (that all the expert object designers are using) that you&apos;ve likely never heard about. &lt;/p&gt;
&lt;h2 id=&quot;About-Responsibility-Driven-Design-RDD&quot; style=&quot;position:relative;&quot;&gt;About Responsibility-Driven Design (RDD)&lt;a href=&quot;#About-Responsibility-Driven-Design-RDD&quot; aria-label=&quot;About Responsibility Driven Design RDD permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Allow me to introduce you to &lt;em&gt;Responsibility Driven Design (RDD)&lt;/em&gt;: the programming world’s most influential, effective, and intentional approach to designing object-oriented software. I know, big claim. But it’s true.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/design/responsibility-driven-design-book.jpg&quot; alt=&quot;Responsibility-Driven Design book&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;My copy of the legendary Object Design book. My &lt;a target=&quot;_blank&quot; href=&quot;https://www.amazon.ca/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215&quot;&gt;second favourite&lt;/a&gt; blue programming book. This book is so rare that it&apos;s nearly $200 USD nowadays!&lt;p&gt;
&lt;p&gt;RDD, originally invented by Rebecca Wirfs-Brock in the late 80s and modernized in her 2002 book titled &lt;em&gt;Object Design&lt;/em&gt; is a learnable and repeatable design method for building object-oriented applications.&lt;/p&gt;
&lt;p&gt;Where most of us today write and think in procedural style code using classes and functions &lt;strong&gt;because it&apos;s often what the languages dictate&lt;/strong&gt;, Responsibility-Driven Design presents an approach to &lt;em&gt;actually&lt;/em&gt; design objects with purpose and intention. &lt;/p&gt;
&lt;h2 id=&quot;Roles-responsibilities-collaborations&quot; style=&quot;position:relative;&quot;&gt;Roles, responsibilities, collaborations&lt;a href=&quot;#Roles-responsibilities-collaborations&quot; aria-label=&quot;Roles responsibilities collaborations permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Object software is neighborhoods of collaborating objects which (polymorphically) come and go, each filling in for roles with related responsibilities.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Role&lt;/strong&gt;: A collection of related responsibilities&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resoponsibility&lt;/strong&gt;: An obligation to &lt;em&gt;do&lt;/em&gt; (some task/behavior) or &lt;em&gt;know&lt;/em&gt; something (some data)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Collaboration&lt;/strong&gt;: An interaction of objects or roles (or both)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To be continued...&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Check out the &lt;a href=&quot;https://en.wikipedia.org/wiki/Responsibility-driven_design&quot;&gt;wikipedia page&lt;/a&gt; on Responsibility-Driven Design and feel to leave comments or questions for when I finish this post.&lt;/p&gt;
&lt;p&gt;Highly recommend reading &lt;a href=&quot;https://www.wirfs-brock.com/Design.html&quot;&gt;this page&lt;/a&gt; and watching &lt;a href=&quot;https://vimeo.com/7722463&quot;&gt;this talk&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[4 Principles of Object-Oriented Programming]]></title><description><![CDATA[Even though I studied object-oriented programming in university, I still struggled with it once I got out into the real world and tried…]]></description><link>https://khalilstemmler.com/articles/object-oriented/programming/4-principles/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/object-oriented/programming/4-principles/</guid><pubDate>Sat, 16 Apr 2022 22:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Even though I studied object-oriented programming in university, I still struggled with it once I got out into the real world and tried using it to develop software. &lt;/p&gt;
&lt;p&gt;I think this has to do with the fact that I was unaware that object design is actually comprised of three parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;analysis&lt;/strong&gt;: where we &lt;a href=&quot;https://wiki.solidbook.io/16-Learning-the-Domain-eb1f4be15f044dc9b5bc3affc5fe23a2&quot;&gt;learn a domain&lt;/a&gt;, discover functional and &lt;a href=&quot;/articles/object-oriented/analysis/non-functional-requirements/&quot;&gt;non-functional requirements&lt;/a&gt;, and turn them into &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;design&lt;/strong&gt;: where we utilize a design method like &lt;a href=&quot;/articles/object-oriented/design/responsibility-driven-design/&quot;&gt;Responsibility-Driven Design&lt;/a&gt; to convert requirements into roles, responsibilities, and collaborations, we consider design patterns and their tradeoffs, we make architectural decisions - deciding on archetectural styles and patterns&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;programming&lt;/strong&gt;: where we map designs into tested, flexible, maintainable code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img style=&quot;width: 100%;&quot; alt=&quot;Object design&quot; src=&quot;/img/blog/object-oriented/programming/4-principles/object-design.svg&quot;&gt;&lt;/img&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Object design is comprised of three parts: Analysis, Design, and Programming&lt;/p&gt;
&lt;p&gt;Only learning the &lt;em&gt;programming&lt;/em&gt; aspect, I found myself confused about what good design looked like, how to turn requirements into objects, and when and why to use concepts like abstraction, encapsulation, inheritance, and polymorphism. Yes, I could somewhat remember what these concepts were, but knowing when and why to use them was unclear to me. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/programming/4-principles/principles-of-oo.png&quot; alt=&quot;Principles of Object Oriented Programming&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;The four main principles of object-oriented programming (abstraction, inheritance, encapsulation, and polymorphism). The core principle is abstraction. Without it, the others couldn&apos;t exist.&lt;/p&gt;
&lt;p&gt;In this post, I want to revisit these four main ideas — these principles of object-oriented programming — discuss why they’re beneficial and explain them with simple, relatable, and practical explanations.&lt;/p&gt;
&lt;h2 id=&quot;Abstraction&quot; style=&quot;position:relative;&quot;&gt;Abstraction&lt;a href=&quot;#Abstraction&quot; aria-label=&quot;Abstraction permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Are you &lt;em&gt;really&lt;/em&gt; aware of &lt;em&gt;how&lt;/em&gt; your TV turns on when you press the ON button on the remote? Do you, as a user, need to know the specific sequence of 0’s and 1’s that your remote control emits to signal to the television’s receiver that it should turn on? Or is pressing the &lt;em&gt;ON&lt;/em&gt; button good enough?&lt;/p&gt;
&lt;p&gt;Are you &lt;em&gt;really&lt;/em&gt; aware of &lt;em&gt;how&lt;/em&gt; your car starts when you turn your key in the ignition? Do you, as a driver, need to know about the ignition switch, how the voltage from the battery hits the ignition coil, how an engine spark gets directed to the spark plugs, and how that ignites the fuel to make the car run? Or is turning the key and hearing a &lt;em&gt;ding-ding&lt;/em&gt; enough?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/programming/4-principles/abstraction-oo.png&quot; alt=&quot;Abstraction OO&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Abstraction makes technology easier to use. Most of us know that pressing the ON button on the remote will turn on a TV. And that&apos;s good enough for us. Imagine that you needed to know the low-level electronic details in order to turn your TV on to watch your favourite HBO show. The learning curve would be tremendous. Very few people would watch TV if that were the case.&lt;/p&gt;
&lt;p&gt;It should be clear that we maneuver the world using abstractions — conceptual models that give us a &lt;em&gt;good enough&lt;/em&gt; understanding of inventions that are much more complex behind the scenes. And in object-oriented programs, &lt;strong&gt;the inventions that we aim to simplify and make easy to use are objects&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Abstraction is a key principle of design. Since object-oriented programs can get quite large, it’s just not humanly possible to expect others to be aware of the inner-workings of each and every class or component within them. Therefore, we strive to abstract objects in a way that makes them &lt;strong&gt;intention-revealing&lt;/strong&gt;, &lt;strong&gt;simple to use&lt;/strong&gt;, and &lt;strong&gt;simple to understand&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;Consider the abstraction of a washing machine. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Options for the wash cycle&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; WashOptions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  dryLevel&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;low&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;medium&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;high&apos;&lt;/span&gt;
  temperature&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;cold&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  duration&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;hour&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  ecoEnabled&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// The abstraction&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;WashingMachine&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	
  &lt;span class=&quot;token comment&quot;&gt;// Private instance variables&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;startCycle&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;options&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; WashOptions&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	  &lt;span class=&quot;token comment&quot;&gt;// Parse the options&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Get access to the physical layer&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Convert options into commands&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Lots of low-level code&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// And so on...&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	
  &lt;span class=&quot;token comment&quot;&gt;// More methods&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Assuming that the only &lt;code class=&quot;language-text&quot;&gt;public&lt;/code&gt; method right now is the &lt;code class=&quot;language-text&quot;&gt;startCycle&lt;/code&gt; method, what else does the client need to know? Does it need to know &lt;em&gt;how&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;startCycle&lt;/code&gt; works? Does it need to know about the &lt;code class=&quot;language-text&quot;&gt;private&lt;/code&gt; instance variables within the class? Does it need to know about any other &lt;code class=&quot;language-text&quot;&gt;private&lt;/code&gt; methods? &lt;/p&gt;
&lt;!-- **show a picture of a washing machine abstraction where it’s super complex, there’s stuff coming out of it, and it’s all visible, etc vs. one that’s sleek, simple, one button on it and that’s pretty much it. or something comparable, a complex machine vs. a simple button to press.** --&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/programming/4-principles/washing-machine-abstraction.png&quot; alt=&quot;Abstraction OO&quot;&gt;&lt;/p&gt;
&lt;p&gt;No, absolutely not. Just like the power-button on the TV remote, it’s simplified for public use. For someone to use this abstraction, all they need to know is the existence of the &lt;code class=&quot;language-text&quot;&gt;startCycle&lt;/code&gt; method and how to call it. That’s it. All other details are abstracted away within the class. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Obtain access to the abstraction&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; WashingMachine &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../washer&apos;&lt;/span&gt;
 
&lt;span class=&quot;token comment&quot;&gt;// Create an instance&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; washer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;WashingMachine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Usage&lt;/span&gt;
washer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;startCycle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  dryLevel&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;medium&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  temperature&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;cold&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  duration&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;hour&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  ecoEnabled&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By keeping what’s not necessary for the client to know &lt;em&gt;abstracted away&lt;/em&gt;, we reduce confusion and make it easy for other developers to know how to use our code and extend it.&lt;/p&gt;
&lt;h3 id=&quot;Abstraction-is-the-root-principle-of-design&quot; style=&quot;position:relative;&quot;&gt;Abstraction is the root principle of design&lt;a href=&quot;#Abstraction-is-the-root-principle-of-design&quot; aria-label=&quot;Abstraction is the root principle of design permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Abstraction has many uses — for both the designer and the client. There is much more that can be said on abstraction and abstraction tools like interfaces, abstract classes and types, such as the fact that they give us:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The ability to design using &lt;em&gt;contracts&lt;/em&gt; vs &lt;em&gt;concretions&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The ability to separate the &lt;em&gt;what&lt;/em&gt; from the &lt;em&gt;how&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The ability to focus on the &lt;em&gt;declarative&lt;/em&gt; separately from the &lt;em&gt;imperative&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The ability to focus on the &lt;em&gt;high-level&lt;/em&gt; ideas separately from the &lt;em&gt;low-level&lt;/em&gt; details.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But for now, I’ll say that it’s the root principle of design and a central point of focus for many other important topics like design patterns, principles, responsibility-driven design and more.&lt;/p&gt;
&lt;h3 id=&quot;div-classexpandable-sectionBonus-Alan-Watts-on-Abstraction-and-Thoughtdiv-classexpandable-section-button-onclicktoggleExpandableSectionalan-wattsdivdiv&quot; style=&quot;position:relative;&quot;&gt;&lt;div class=&quot;expandable-section&quot;&gt;Bonus: Alan Watts on Abstraction (and Thought)&lt;div class=&quot;expandable-section-button&quot; onclick=&quot;toggleExpandableSection(&apos;alan-watts&apos;)&quot;&gt;+&lt;/div&gt;&lt;/div&gt;&lt;a href=&quot;#div-classexpandable-sectionBonus-Alan-Watts-on-Abstraction-and-Thoughtdiv-classexpandable-section-button-onclicktoggleExpandableSectionalan-wattsdivdiv&quot; aria-label=&quot;div classexpandable sectionBonus Alan Watts on Abstraction and Thoughtdiv classexpandable section button onclicktoggleExpandableSectionalan wattsdivdiv permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div id=&quot;alan-watts&quot; class=&quot;expandable-section-content&quot;&gt;
  &lt;p&gt;From Alan Watts&apos; lecture titled &quot;The Silent Mind&quot;&lt;p&gt;
  &lt;p&gt;&quot;To think, we use a series of images or very simple grasps of the world, and these are abstractions.&quot;&lt;/p&gt;
  &lt;iframe width=&quot;100%&quot; height=&quot;350px&quot; src=&quot;https://www.youtube.com/embed/3rq0GKYx-LE&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;h3 id=&quot;Also-see&quot; style=&quot;position:relative;&quot;&gt;Also see&lt;a href=&quot;#Also-see&quot; aria-label=&quot;Also see permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Abstraction is the macro-level principle. Here are a few micro-level topics which are directly related.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://wiki.solidbook.io/Part-II-Humans-&amp;#x26;-Code-dd6967bd89db4ad9bf505f12fc7289b4&quot;&gt;Humans &amp;#x26; Code&lt;/a&gt;: How can we tell if our projects are pleasant to work with? We need to understand how we &lt;em&gt;understand&lt;/em&gt;. This section of solidbook introduces the principles of Human-Centered Design and techniques to develop more human-friendly codebases.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/oop-design-principles/maintain-a-single-layer-of-abstraction&quot;&gt;Maintain a Single Layer of Abstraction at a Time&lt;/a&gt;: Keep your methods cohesive and readable by maintaining a single layer of abstraction at a time. Understand what responsibilities for &lt;em&gt;doing&lt;/em&gt; and &lt;em&gt;knowing&lt;/em&gt; your class has and stick to it.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://martinfowler.com/bliki/MinimalInterface.html&quot;&gt;Minimal Interface&lt;/a&gt;: Boil the public API (of a class, component, or service) down to the smallest set of operations possible that lets people do what they need to do. May not be the most human-friendly, but operations can be combined in ways that let clients accomplish their goals.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://martinfowler.com/bliki/HumaneInterface.html&quot;&gt;Humane Interface&lt;/a&gt;: Find out what people want to do and then design the interface in a way that represents it in the most &lt;em&gt;human-centered&lt;/em&gt; language possible.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.stanford.edu/~ouster/cgi-bin/cs190-spring16/lecture.php?topic=modularDesign&quot;&gt;Thin Interfaces, thick implementations&lt;/a&gt;: Stanford Computer Science Professor John Ousterhout&apos;s idea is design thin interfaces with thick implementations. This idea further reinforces that abstraction is about making interfaces easy to understand and use while hiding away complex details.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Inheritance&quot; style=&quot;position:relative;&quot;&gt;Inheritance&lt;a href=&quot;#Inheritance&quot; aria-label=&quot;Inheritance permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Wouldn’t it be nice if we could reuse code or extend it for more specific use cases? That’s what inheritance is about.&lt;/p&gt;
&lt;p&gt;To go about code reuse, in &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/introduction-to-tdd/&quot;&gt;TDD&lt;/a&gt;, we have this technique called the &lt;em&gt;Rule of Three&lt;/em&gt; which specifies that upon seeing duplication three times, we should refactor it into an abstraction.&lt;/p&gt;
&lt;p&gt;The classic example I use to demonstrate is one where we rely on several different API endpoints from a front-end application but we duplicate the fetching logic across each API adapter (think &lt;code class=&quot;language-text&quot;&gt;/users&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;/forum&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;/billing&lt;/code&gt;, etc).&lt;/p&gt;
&lt;!-- **Put a picture here with common logic showing, etc** --&gt;
&lt;p&gt;Instead, what we &lt;em&gt;could&lt;/em&gt; do is refactor the data-fetching logic into a common place. The &lt;a href=&quot;https://khalilstemmler.com/blogs/typescript/abstract-class/&quot;&gt;abstract class&lt;/a&gt; is a good tool for this use case.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Base API&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;API&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; baseUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; axiosInstance&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AxiosInstance&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;baseUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;baseUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; baseUrl
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;axiosInstance &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; axios&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;enableInterceptors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;enableInterceptors&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token comment&quot;&gt;// Here&apos;s where you can define common refetching logic&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Common &quot;get&quot; logic&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; (url: string, requestConfig?: RequestConfig): Promise&amp;lt;AxiosResponse&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;axiosInstance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;(`${this.baseUrl}/${url}`, &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      headers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; requestConfig&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;headers &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; requestConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      params&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; requestConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; requestConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token plain-text&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;  // Common &quot;post&quot; logic&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token plain-text&quot;&gt;  protected post&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; (url: string, requestConfig?: RequestConfig): Promise&amp;lt;AxiosResponse&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;axiosInstance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;post&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;(`${this.baseUrl}/${url}`, &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      headers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; requestConfig&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;headers &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; requestConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      params&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; requestConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; requestConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token plain-text&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token plain-text&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then, for each API adapter we need, we can merely subclass the base API abstract class to get access to the common functionality (&lt;code class=&quot;language-text&quot;&gt;public&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;protected&lt;/code&gt; methods and properties). &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Users API&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UsersAPI&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;API&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;http://example.com/users&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
 
  &lt;span class=&quot;token comment&quot;&gt;// High-level functionality (extending it)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getUsers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Users&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Use the common logic from the base class&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;users &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Users
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;  &lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;  ...&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;// Forum API&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;export class ForumAPI extends API &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;http://example.com/forum&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
 
  &lt;span class=&quot;token comment&quot;&gt;// High-level functionality (extending it)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPosts&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Posts&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Here, as well&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;posts &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Posts&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;  &lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;  ...&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;// Billing API&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;export class BillingAPI extends API &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;http://example.com/billing&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
 
  &lt;span class=&quot;token comment&quot;&gt;// High-level functionality (extending it)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPayments&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Payments&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// And here ;)&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;payments &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Payments&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;  &lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;  ...&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Inheritance relies on the principle of abstraction; with it, we gain the ability to abstract away (duplicated) low-level details to the base class (&lt;code class=&quot;language-text&quot;&gt;API&lt;/code&gt;) so that the subclasses can focus on the (unique) high-level details (&lt;code class=&quot;language-text&quot;&gt;UsersAPI&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;ForumAPI&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;BillingAPI&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/programming/4-principles/inheritance.png&quot; alt=&quot;Abstraction OO&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;A good reason to refactor using inheritance is to clean up duplication and make generic functionality easier to use for more specific objects.&lt;/p&gt;
&lt;h3 id=&quot;Its-about-reuse-not-hierarchies&quot; style=&quot;position:relative;&quot;&gt;It’s about reuse, not hierarchies&lt;a href=&quot;#Its-about-reuse-not-hierarchies&quot; aria-label=&quot;Its about reuse not hierarchies permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When most developers learn about inheritance, they’re presented with trivial &lt;em&gt;Animal-Dog&lt;/em&gt; or &lt;em&gt;Person-Staff-Teacher&lt;/em&gt; examples which map nicely to the real world but manifest real problems with the complex hierarchies they create.&lt;/p&gt;
&lt;p&gt;It is very important to note that concepts which exist in the real world often do not translate into useful software objects. For example, it’s probably not important to model the hierarchy of a car’s speed, dimensions, upgrades, parts, and window tint within the context of an online oil change booking form. However, in the design of a multiplayer racing game, they may very well be useful and necessary.&lt;/p&gt;
&lt;p&gt;Why do we invent abstractions anyway? What&apos;s the point? To help us express what we need to express to meet the requirements, and to do so in a maintainable way — that’s it. As I&apos;ve written about in &lt;a href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt;, the goal of software design is to write code that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Meet the needs of the customer and &lt;/li&gt;
&lt;li&gt;Is cost-effectively changed by developers&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;Inheritance used properly helps #2. Therefore, inheritance is a tool we use upon finding opportunities for reuse, not to express &lt;em&gt;real-world hierarchical similarities.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;At the heart of object-oriented software development there is a violation of real-world physics. We have a license to reinvent the world, because modeling the real world in our machinery is not our goal.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;— Rebecca Wirfs-Brock via Object Design [2002]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;Composition--delegation&quot; style=&quot;position:relative;&quot;&gt;Composition &amp;#x26; delegation&lt;a href=&quot;#Composition--delegation&quot; aria-label=&quot;Composition  delegation permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If inheritance is really just about reuse (and not about world-building), then that means we can skip the hierarchy entirely and use the techniques of composition and delegation to implement inheritance. &lt;/p&gt;
&lt;!-- **Picture of is-a, has-a both working to help perform reuse — how am I going to draw is a and has a?** --&gt;
&lt;p&gt;That means we could also refactor the duplication of the HTTP logic like this.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UsersAPI&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	
  &lt;span class=&quot;token comment&quot;&gt;// Compose using dependency injection&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;http&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;API&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;http &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;baseURL &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;https://example.com/users&apos;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token function&quot;&gt;getUsers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;baseURL&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Therefore, if we encounter duplication, we have a lot of refactoring techniques:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Inheritance (Extract superclass)&lt;/strong&gt;: When you have two or more classes with common methods or fields, create a superclass and inherit the shared behavior.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Composition (Extract class)&lt;/strong&gt;: When one class does work for two or more classes, extract the related methods to its own class and compose your reliant classes with the new one.&lt;/li&gt;
&lt;/ul&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Rule of thumb — only inherit from contracts, not concretions:&lt;/b&gt; If you’re going to use inheritance the classic OO way, I generally advise that you only inherit or extend from contracts (interfaces, abstract classes, types) and not from concretions (classes). There’s a design method which explains why this rule makes sense (see Responsibility-Driven Design), but as a quick rule of thumb, you’ll know if you’re using inheritance poorly if you find yourself needing to subclass a concrete class.&lt;/p&gt;
&lt;h2 id=&quot;Encapsulation&quot; style=&quot;position:relative;&quot;&gt;Encapsulation&lt;a href=&quot;#Encapsulation&quot; aria-label=&quot;Encapsulation permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Objects contain state, make decisions based on that state, and relay messages to other objects asking them for help to fetch or compute things, like a network of routers or a web of atoms. &lt;/p&gt;
&lt;p&gt;Because objects make decisions (and enact business logic) based on their state, it’s important that each object manage its own state and protect against mutations from outside classes. Failure to do so can lead to strange behavior, bugs, and an &lt;a href=&quot;https://khalilstemmler.com/wiki/anemic-domain-model/&quot;&gt;anemic domain model&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Encapsulation is the technique of making state &lt;code class=&quot;language-text&quot;&gt;private&lt;/code&gt;. Encapsulation means that the class which owns the state decides the degree to which state can be accessed and changed. This is done through the use of &lt;code class=&quot;language-text&quot;&gt;public&lt;/code&gt; methods.&lt;/p&gt;
&lt;p&gt;Let’s continue to demonstrate with the washing machine example. Depending on the washing machine’s current state, some behaviours are valid while others are invalid.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/programming/4-principles/washing-machine.png&quot; alt=&quot;washing machine&quot;&gt;&lt;/p&gt;
&lt;p&gt;For example, if the machine is currently &lt;code class=&quot;language-text&quot;&gt;ON&lt;/code&gt; , it is valid to call &lt;code class=&quot;language-text&quot;&gt;turnOff()&lt;/code&gt; to turn the machine &lt;code class=&quot;language-text&quot;&gt;OFF&lt;/code&gt;. If the machine is in the &lt;code class=&quot;language-text&quot;&gt;WASH&lt;/code&gt; state, it’s OK to call &lt;code class=&quot;language-text&quot;&gt;pause()&lt;/code&gt;  to put the machine into the &lt;code class=&quot;language-text&quot;&gt;PAUSED&lt;/code&gt; state. But if the machine is &lt;code class=&quot;language-text&quot;&gt;OFF&lt;/code&gt; (or &lt;code class=&quot;language-text&quot;&gt;ON&lt;/code&gt; for that matter) it would &lt;em&gt;not&lt;/em&gt; be valid to call &lt;code class=&quot;language-text&quot;&gt;PAUSE&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;Why? Because a washing machine can’t go from being &lt;code class=&quot;language-text&quot;&gt;OFF&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;PAUSED&lt;/code&gt;. It doesn’t make sense.&lt;/p&gt;
&lt;p&gt;Encapsulation is the mechanism that governs these rules (also known as &lt;a href=&quot;https://khalilstemmler.com/wiki/invariant/&quot;&gt;class invariants&lt;/a&gt;) for us.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; WashState &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;OFF&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ON&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;WASH&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;PAUSED&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;DONE&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Cycle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;COOL&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;WARM&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; MachineState &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  washState&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; WashState&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  currentCycle&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Cycle&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;WashingMachine&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Encapsulation of state is achieved here by making&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// state private and inaccessible directly.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; MachineState&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	
  &lt;span class=&quot;token comment&quot;&gt;// Access is provided via public methods&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getWashState&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; WashState &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;washState&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getCurrentCycle&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Cycle &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;currentCycle&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// State is changed only through the use of public&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// mutator methods&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;pause&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Note this important business logic which is encapsulated&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// to the correct place. The related data and behavior live&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// together.&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// We ONLY do the pause logic if the current state is&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &apos;WASH&apos;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;washState &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;WASH&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Stop washing&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Cue pause sound&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Set new state&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;washState &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;PAUSED&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Given this, client usage may look as follows:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;washer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;startCycle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  dryLevel&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;medium&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  temperature&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;cold&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  duration&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;hour&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  ecoEnabled&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;washer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getWashState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &apos;WASH&apos;&lt;/span&gt;
washer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pause&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;washer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getWashState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &apos;PAUSED&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Encapsulation combines together the data and related behavior which — like abstraction — simplifies usage, but also acts as a single place for us to put relevant logic. With this technique, we invent single sources of truth and obtain appropriate places to locate logic once and for all. &lt;/p&gt;
&lt;h2 id=&quot;Polymorphism&quot; style=&quot;position:relative;&quot;&gt;Polymorphism&lt;a href=&quot;#Polymorphism&quot; aria-label=&quot;Polymorphism permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Polymorphism is about “taking on many shapes”. It&apos;s about designing your &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt; and algorithms in such a way that we &lt;em&gt;always&lt;/em&gt; get the same &lt;em&gt;high-level&lt;/em&gt; behavior, but we allow for dynamic &lt;em&gt;low-level behavior&lt;/em&gt; at runtime.&lt;/p&gt;
&lt;!-- Again, thanks to the root principle of abstraction, we can define the mandatory high-level policy and expect that it will be fulfilled with potentially unique low-level behavior at runtime. --&gt;
&lt;p&gt;I still think the best real-world examples I can provide are either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/blogs/typescript/abstract-class/#2-Template-method-design-pattern-front-end-libraries--frameworks-example&quot;&gt;the React component example&lt;/a&gt; or&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/solid-principles/solid-typescript/#Liskov-Substition-Principle&quot;&gt;the email sending service example using the Liskov-Subsitution Principle&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Regardless, let&apos;s demonstrate with an example that will let me introduce you to the idea of &lt;em&gt;roles&lt;/em&gt; from &lt;a href=&quot;/articles/object-oriented/design/responsibility-driven-design/&quot;&gt;Responsibility-Driven Design&lt;/a&gt; (the &lt;em&gt;actual&lt;/em&gt; way to do OO correctly as far as I know). Think about the role of a &lt;em&gt;clerk&lt;/em&gt; at a grocery store. What’s a clerk supposed to do? Answer questions, scan products, bag your items, and prompt you for payment, right? So you could say those are the &lt;em&gt;responsibilities&lt;/em&gt; of a clerk. &lt;/p&gt;
&lt;!-- **Draw a picture of the role of the employee and the responsibilities they have to fill and then also draw each of the employees pointing to the role of the clerk.**  --&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/programming/4-principles/clerk-role-responsibility-collaborations-crc-card.png&quot; alt=&quot;Clerk Role Responsibilities Collaborations CRC card&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;A clerk CRC card that defines the role of a clerk, the related responsibilities and the collaborations it has.&lt;/p&gt;
&lt;p&gt;Now let’s say that there are 4 different employees that work at this grocery store. Each one can take on the role of a &lt;em&gt;clerk&lt;/em&gt;. There’s James who is generally pretty snappy, Mariah who can be somewhat brooding, Max who is always on time (and the friendliest person you’ve ever met), and Mark who is actually the manager but will sometimes fill in when they’re short staffed.&lt;/p&gt;
&lt;p&gt;It’s clear that each of the employees does their job slightly differently, but they still perform the responsibilities that a &lt;em&gt;clerk&lt;/em&gt; should perform. That is, they are &lt;a href=&quot;https://khalilstemmler.com/wiki/concrete-class&quot;&gt;concrete classes&lt;/a&gt; which implement the contract of a &lt;code class=&quot;language-text&quot;&gt;Clerk&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&apos;s represent the contract using an interface.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Clerk&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;answerQuestion&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;question&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Answer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;scanProduct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;bagProduct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;promptForPayment&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;customer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Customer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PaymentResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, we could realize the concretions by implementing the &lt;code class=&quot;language-text&quot;&gt;Clerk&lt;/code&gt; interface, handling things with slighly different behavior if we wish.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClerkJames&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Clerk&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;answerQuestion&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;question&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Answer &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Implement uniquely to James&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;scanProduct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Implement uniquely to James&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;bagProduct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Implement uniquely to James&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;promptForPayment&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;customer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Customer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PaymentResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Implement uniquely to James&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClerkMariah&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Clerk&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;answerQuestion&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;question&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Answer &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Implement uniquely to Mariah&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;scanProduct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Implement uniquely to Mariah&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;bagProduct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Implement uniquely to Mariah&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;promptForPayment&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;customer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Customer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PaymentResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Implement uniquely to Mariah&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Implement the others&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then finally, in the code that relies on a &lt;code class=&quot;language-text&quot;&gt;Clerk&lt;/code&gt;, we&apos;d provide a &lt;code class=&quot;language-text&quot;&gt;Clerk&lt;/code&gt; and a &lt;code class=&quot;language-text&quot;&gt;Customer&lt;/code&gt; to check out.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;checkoutCustomer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;clerk&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Clerk&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; customer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Customer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PaymentResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; question &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; customer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getQuestions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    clerk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;answer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;question&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; product &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; customer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getProductsInCart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    clerk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;scanProduct&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    clerk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bagProduct&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; clerk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;promptForPayment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;customer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that this function relies on a &lt;code class=&quot;language-text&quot;&gt;Clerk&lt;/code&gt;, not a &lt;code class=&quot;language-text&quot;&gt;ClerkJames&lt;/code&gt; or a &lt;code class=&quot;language-text&quot;&gt;ClerkMariah&lt;/code&gt; (or so on). Therefore, it doesn’t matter who shows up to work to fill the role. It could be James, Mariah, Max, or Mark — doesn’t matter. All that matters is that &lt;em&gt;some object with the role of clerk&lt;/em&gt; is supplied and that fully implements the requirements of the contract for a &lt;code class=&quot;language-text&quot;&gt;Clerk&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; customer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Customer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; clerkJames&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ClerkJames &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClerkJames&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; clerkMariah&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ClerkMariah &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClerkMariah&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;checkoutCustomer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;clerkJames&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; customer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Valid&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;checkoutCustomer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;clerkMariah&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; customer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Also valid since it&apos;s a `Clerk`&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Do you see how this works? By relying on a &lt;em&gt;contract&lt;/em&gt; instead of a &lt;em&gt;concretion&lt;/em&gt;, we gain the ability to sub in for different possible implementations.&lt;/p&gt;
&lt;p&gt;This is what polymorphism is about. Dynamic runtime behavior. Substitutability. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/object-oriented/programming/4-principles/clerk.svg&quot; alt=&quot;Clerk polymorphism&quot;&gt;&lt;/p&gt;
&lt;p&gt;What I want for you to take away from this example is that the idea of relying on roles/contracts can be very effective. Within the context of a clean/hexagonal/ports and adapters architecture, the most common reasons you&apos;ll do this is to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keep core code separate from infrastructure code using &lt;a href=&quot;https://khalilstemmler.com/articles/tutorials/dependency-injection-inversion-explained&quot;&gt;dependency inversion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Keep application layer use cases pure so that they can be unit tested. Swap out an infrastructure dependency (&lt;code class=&quot;language-text&quot;&gt;StripeAPI&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;PaypalAPI&lt;/code&gt;) with a test double (&lt;code class=&quot;language-text&quot;&gt;MockPaymentAPI&lt;/code&gt;) so that we don&apos;t make real calls to external services or infrastructure during testing.&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- Draw a picture here where it doesn&apos;t matter who relies on the paymentAPI (contract); and then it shows a StripeAPI, PaypalAPI, and a MockPaymentAPI. Give this extra example to drive the point home, and draw parallels between the clerks and so on.  --&gt;
&lt;h3 id=&quot;Also-see-1&quot; style=&quot;position:relative;&quot;&gt;Also see&lt;a href=&quot;#Also-see-1&quot; aria-label=&quot;Also see 1 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;React components are an example of polymorphism&lt;/b&gt;: I&apos;ve mentioned it before, but in React, the Component class is an example of polymorphism. By extending the component class and implementing the render() method, we create dynamic runtime behavior (where the dynamic behavior is &lt;i&gt;how&lt;/i&gt; our components get rendered). Read more &lt;a href=&quot;https://khalilstemmler.com/blogs/typescript/abstract-class/#2-Template-method-design-pattern-front-end-libraries--frameworks-example&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Rule of thumb — switch statements (conditionals) can be refactored to polymorphism&lt;/b&gt;: Most of the time, if we’re dealing with three or more conditionals in a particular block (and we expect to add more conditions), it could be a good idea to refactor to polymorphism. Extract the generic/common behavior to a contract (abstract class or interface) and put the specific behavior in subclasses. Then program against the contract and allow dynamic runtime binding to work its magic.&lt;/p&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Abstraction, encapsulation, inheritance, and polymorphism are four of the main principles of object-oriented programming. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Abstraction lets us selectively focus on the high-level and abstract way the low-level details.&lt;/li&gt;
&lt;li&gt;Inheritance is about code reuse, not hierarchies.&lt;/li&gt;
&lt;li&gt;Encapsulation keeps state private so that we can better enforce business rules, protect model invariants, and develop a single source of truth for related data and logic.&lt;/li&gt;
&lt;li&gt;Polymorphism provides the ability for us to design for dynamic runtime behavior, easy extensibility, and substitutability.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[What are Dependencies, Composition, Delegation, and Aggregation in Object-Oriented Programming?]]></title><description><![CDATA[Dependency: The Address object comes from outside, it's allocated somewhere else. This means that the Address and Employee objects exists…]]></description><link>https://khalilstemmler.com/articles/object-oriented/programming/dependency-composition-delegation-aggregation/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/object-oriented/programming/dependency-composition-delegation-aggregation/</guid><pubDate>Sat, 16 Apr 2022 22:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Dependency: The Address object comes from outside, it&apos;s allocated somewhere else. This means that the Address and Employee objects exists separately, and only depend on each other.&lt;/p&gt;
&lt;p&gt;Composition: Here you see that a new Engine is created inside Car. The Engine object is part of the Car. This means that a Car is composed of an Engine.&lt;/p&gt;
&lt;p&gt;Composition is about the relationships between objects.&lt;/p&gt;
&lt;p&gt;Delegation is about passing work from one object to another.&lt;/p&gt;
&lt;p&gt;These are actually different (but sometimes related) concerns.&lt;/p&gt;
&lt;p&gt;What you&apos;ve got is B composed of A (B refers to A).&lt;/p&gt;
&lt;p&gt;Aggregation &amp;#x26; composition: An aggregation is an object that represents a concept as a whole and handles managing how its parts are accessed and changed. Composition is related but it adds an additional meaning to aggregation. Composition says that parts of the aggregation can’t exist independently (ie: a wheel can’t exist unless it belongs to a car).&lt;/p&gt;
&lt;p&gt;So dependency == aggregation? stackoverflow.com/questions/11881552/… –
danihodovic
Jan 9, 2014 at 15:04
@dani-h No, aggregation and composition describe how things are build/structured, while dependency is more a property of a certain structure. See @TheLostMind&apos;s great answer&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Is DDD Overrated? | Domain-Driven Design]]></title><description><![CDATA[Is Domain-Driven Design (DDD) overrated? In my opinion, you can only say DDD is overrated once you've achieved mastery over it. At this…]]></description><link>https://khalilstemmler.com/blogs/domain-driven-design/is-ddd-overrated/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/domain-driven-design/is-ddd-overrated/</guid><pubDate>Fri, 08 Apr 2022 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Is &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design (DDD)&lt;/a&gt; overrated?&lt;/p&gt;
&lt;p&gt;In my opinion, you can only say DDD is overrated once you&apos;ve achieved mastery over it. At this point, you can toss it aside. All the tactical patterns, techniques, approaches — you&apos;ve already absorbed the wisdom. You&apos;re the boss. You don&apos;t need rules, cerimonies, &lt;em&gt;other peoples&apos; best practices&lt;/em&gt;. You set your own rules. Because you understand design, you know what&apos;s good, bad, too much design, too little, what the correct amount thereof is (see &lt;a href=&quot;https://en.wikipedia.org/wiki/Golden_mean_(philosophy)&quot;&gt;the Golden Mean&lt;/a&gt;) — you now have room to experiment and get creative.&lt;/p&gt;
&lt;p&gt;If you&apos;re an experienced developer (perhaps &lt;a href=&quot;https://tilkov.com/post/2021/03/01/ddd-is-overrated/&quot;&gt;like the author of this excellent post of the same title&lt;/a&gt;), you&apos;ve likely witnessed the rise of &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt;, &lt;a href=&quot;https://wiki.solidbook.io/Part-V-Object-Oriented-Design-(With-Tests)-7c9c10572cc54aa195e8ec661cf88312&quot;&gt;responsibility-driven design&lt;/a&gt;, and have experience with various approaches to object-oriented and functional software. &lt;/p&gt;
&lt;p&gt;For you, yes. DDD may very well be overrated.&lt;/p&gt;
&lt;p&gt;But for everyone else — the junior developers, the fresh developers, the devs who don&apos;t know software design, the devs still struggling to learn where to put their business logic — DDD is a game-changer.&lt;/p&gt;
&lt;p&gt;To quote Eric Elliot, &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;99% of fresh CS grads don&apos;t know the basics of software design&quot;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Since DDD is a very human approach to design, developers w/o software design experience who study it gain two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;How to write code for humans&lt;/li&gt;
&lt;li&gt;A shortcut to some of the most important design concepts&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That being said, we should eventually leave DDD and look beyond it to fully understand software design, otherwise we treat DDD as a sort of dogma.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A developer will read the DDD material and think, &quot;Well that&apos;s it. I&apos;ve learned the secrets.&quot; When all they&apos;ve learned is the rudiments of one angle on software design. - &lt;a href=&quot;https://twitter.com/sbellware/status/1498789073749778432&quot;&gt;via Scott Bellware&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Other great approaches exist as well, like Responsibility Driven Design... and if you look closely, you&apos;ll see a lot of similarities to DDD (look into &lt;a href=&quot;https://khalilstemmler.com/articles/object-oriented/design/object-stereotypes/&quot;&gt;Object Stereotypes&lt;/a&gt; and see how a &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-value-object&quot;&gt;Value Object&lt;/a&gt; or an &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/entities/&quot;&gt;Entity&lt;/a&gt; is essentially an &lt;em&gt;Information Holder&lt;/em&gt; object stereotype).&lt;/p&gt;
&lt;p&gt;What do these similarities tell us? That we&apos;re close to some ineffable truths or laws of design. Or at least a little further into our discovery of the mystery that is software design.&lt;/p&gt;
&lt;h2 id=&quot;Summary&quot; style=&quot;position:relative;&quot;&gt;Summary&lt;a href=&quot;#Summary&quot; aria-label=&quot;Summary permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In summary,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every developer should learn DDD&lt;/li&gt;
&lt;li&gt;Every developer should then learn the truths of software design that make DDD effective&lt;/li&gt;
&lt;li&gt;Every developer should then abandon anything cerimonious about DDD and develop their own style based on their own experience&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Update: I'm Teaching Software Design & Architecture Full-time @ khalilstemmler.com]]></title><description><![CDATA[Well, everybody. The time has come.  March 31st, 2022 was my last day at Apollo GraphQL. After about 3 years, countless blog posts, 4 talks…]]></description><link>https://khalilstemmler.com/blogs/life/2022-fulltime/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/life/2022-fulltime/</guid><pubDate>Wed, 06 Apr 2022 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Well, everybody. The time has come. &lt;/p&gt;
&lt;p&gt;March 31st, 2022 was my last day at Apollo GraphQL. After about 3 years, countless blog posts, 4 talks, 3 trips, I&apos;m stepping away from my Apollo fam to focus on teaching devs how to write testable, flexible, maintainable code.&lt;/p&gt;
&lt;p&gt;I&apos;m going to miss the team; and while I believe that the supergraph is seriously the future, duty calls. I&apos;m returning to focus primarily on my book, courses, blog, videos, and open source work.&lt;/p&gt;
&lt;h2 id=&quot;Why-I-started-this-blog&quot; style=&quot;position:relative;&quot;&gt;Why I started this blog&lt;a href=&quot;#Why-I-started-this-blog&quot; aria-label=&quot;Why I started this blog permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I started this blog in 2019 after having successfully &lt;em&gt;tanked the quality of the code&lt;/em&gt; for my own startup company called Univjobs. &lt;/p&gt;
&lt;p&gt;Freshly graduated from university, I was surprised at how ill-prepared I actually was in the craft of software design. &lt;/p&gt;
&lt;p&gt;Not knowing how to organize business logic, write tests, or write code in a way that it gets better instead of &lt;em&gt;worse&lt;/em&gt; after time, I sought out answers. I decided that I was going to study, practice, and master the craft of software design.&lt;/p&gt;
&lt;h3 id=&quot;Best-hits&quot; style=&quot;position:relative;&quot;&gt;Best hits&lt;a href=&quot;#Best-hits&quot; aria-label=&quot;Best hits permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The most popular articles I&apos;ve written from 2019-2021 are:&lt;/p&gt;
&lt;ul class=&quot;special-quote&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/domain-driven-design-intro/&quot;&gt;An Introduction to Domain-Driven Design - DDD w/ TypeScript&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/client-side-architecture/introduction/&quot;&gt;Client-Side Architecture Basics&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/full-stack-software-design/&quot;&gt;How to Learn Software Design and Architecture | The Full-stack Software Design &amp; Architecture Map&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/introduction-to-tdd/&quot;&gt;Introduction to Test-Driven Development (TDD) with Classic TDD Example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solidbookio&quot; style=&quot;position:relative;&quot;&gt;solidbook.io&lt;a href=&quot;#solidbookio&quot; aria-label=&quot;solidbookio permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Documenting my learnings here on the blog and within solidbook.io (a guide to software design and architecture), over 2500 developers have purchased the book!&lt;/p&gt;
&lt;p&gt;I&apos;ve been blown away by the feedback I&apos;ve received even though it&apos;s only about halfway done (and only a first draft)! Not only that, but the open source project we build in the book, &lt;a href=&quot;https://github.com/stemmlerjs/ddd-forum&quot;&gt;DDDForum&lt;/a&gt;, has over 1200 stars and 240 forks.&lt;/p&gt;
&lt;p&gt;Thank you everyone for your support, feedback, and PATIENCE - especially you early book readers. I appreciate you tremendously.&lt;/p&gt;
&lt;h2 id=&quot;To-mastery&quot; style=&quot;position:relative;&quot;&gt;To mastery&lt;a href=&quot;#To-mastery&quot; aria-label=&quot;To mastery permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;“Rule of thumb: The more important a call or action is to our soul&apos;s evolution, the more Resistance we will feel toward pursuing it.”
― Steven Pressfield, The War of Art: Winning the Inner Creative Battle&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Complexity is chief antagonist of well-crafted software. A naturally occuring phenomenon, if we do nothing about it, it will only get worse. To you, the reader:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;who is learning how to write code that fans the flame of complexity &lt;/li&gt;
&lt;li&gt;who is thinking strategically about feature-development because you know that &quot;just making it work&quot; &lt;em&gt;once&lt;/em&gt; != good code &lt;/li&gt;
&lt;li&gt;who is learning how to use tests to gain consistency and reliability in their work&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To you developers - you who feel the pull...&lt;/p&gt;
&lt;p&gt;... where are we going?&lt;/p&gt;
&lt;p&gt;To mastery.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Hash Tables | What, Why & How to Use Them]]></title><description><![CDATA[On this site, we're primarily concerned with software design, architecture, and the many problems that occur later on in your developer…]]></description><link>https://khalilstemmler.com/blogs/data-structures-algorithms/hash-tables/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/data-structures-algorithms/hash-tables/</guid><pubDate>Wed, 19 Jan 2022 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;On this site, we&apos;re primarily concerned with software design, architecture, and the many problems that occur later on in your developer journey, like &lt;a href=&quot;https://khalilstemmler.com/blogs/tooling/enforcing-husky-precommit-hooks/&quot;&gt;keeping code clean&lt;/a&gt;, &lt;a href=&quot;https://khalilstemmler.com/articles/domain-driven-design-intro/&quot;&gt;handling complexity&lt;/a&gt;, and &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/introduction-to-tdd/&quot;&gt;writing testable code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Early on, when you&apos;re primarily concerned with learning the ins and outs of a language, you&apos;ll find yourself also need to master the algorithmic basis of software development — code in methods and functions. One of the most integral tools to solving these problems? Data structures.&lt;/p&gt;
&lt;p&gt;I want to talk about one of the most important data structures: the hash table.&lt;/p&gt;
&lt;p&gt;In this article, we’ll begin by learning what hash tables are and why you&apos;d want to use them. Then we’ll look at different hash tables implementations and closely related data structures. Finally, we wrap with a discussion of which hash table implementation you should reach most of the time and discuss some of the most common use cases for hash tables.&lt;/p&gt;
&lt;h2 id=&quot;What-is-a-hash-table&quot; style=&quot;position:relative;&quot;&gt;What is a hash table?&lt;a href=&quot;#What-is-a-hash-table&quot; aria-label=&quot;What is a hash table permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A hash table is a data structure that you can use to store data in key-value format with direct access to its items in constant time.&lt;/p&gt;
&lt;p&gt;Hash tables are said to be &lt;em&gt;associative&lt;/em&gt;, which means that for each key, data occurs at most once. Hash tables let us implement things like phone books or dictionaries; in them, we store the association between a value (like a dictionary definition of the word &quot;lamp&quot;) and its key (the word &quot;lamp&quot; itself).&lt;/p&gt;
&lt;p&gt;We can use hash tables to store, retrieve, and delete data uniquely based on their &lt;strong&gt;unique key&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Why-use-hash-tables&quot; style=&quot;position:relative;&quot;&gt;Why use hash tables?&lt;a href=&quot;#Why-use-hash-tables&quot; aria-label=&quot;Why use hash tables permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The most valuable aspect of a hash table over other abstract data structures is its &lt;strong&gt;speed&lt;/strong&gt; to perform insertion, deletion, and search operations. Hash tables can do them all in constant time.&lt;/p&gt;
&lt;p&gt;For those unfamiliar with time complexity (big O notation), constant time is the fastest possible time complexity. Hash tables can perform nearly all methods (except &lt;em&gt;list&lt;/em&gt;) very fast in O(1) time.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Algorithm&lt;/th&gt;
&lt;th&gt;Average&lt;/th&gt;
&lt;th&gt;Worst case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;List&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Search&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insert&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete&lt;/td&gt;
&lt;td&gt;O(1)&lt;/td&gt;
&lt;td&gt;O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Because of this efficiency, you&apos;ll find hash tables to be pretty dang useful for many use cases. And if you look carefully, you’ll notice that they’re actually implemented in a variety of places throughout your tools like your databases, caches, data-fetching libraries, and so on.&lt;/p&gt;
&lt;p&gt;We’ll expand on some of the uses cases for hash tables later on in the article.&lt;/p&gt;
&lt;h2 id=&quot;How-do-hash-tables-work&quot; style=&quot;position:relative;&quot;&gt;How do hash tables work?&lt;a href=&quot;#How-do-hash-tables-work&quot; aria-label=&quot;How do hash tables work permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are four distinct aspects to discuss how hash tables work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;storage&lt;/li&gt;
&lt;li&gt;key-value pairs&lt;/li&gt;
&lt;li&gt;a hashing function&lt;/li&gt;
&lt;li&gt;table operations&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Storage&quot; style=&quot;position:relative;&quot;&gt;Storage&lt;a href=&quot;#Storage&quot; aria-label=&quot;Storage permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A hash table is an abstract data type that relies on using a more primitive data type (such as an array or an object) to store the data. You can use either, but slight implementation implications occur depending on what you choose. We&apos;ll discuss those nuances in detail later on.&lt;/p&gt;
&lt;h3 id=&quot;Key-value-pairs&quot; style=&quot;position:relative;&quot;&gt;Key-value pairs&lt;a href=&quot;#Key-value-pairs&quot; aria-label=&quot;Key value pairs permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Regardless of the underlying primitive data structure, you use to store data, to store data as a &lt;strong&gt;value&lt;/strong&gt; in a hash table, we need some way to identify it uniquely. We need a &lt;strong&gt;key&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Sometimes data contains an individual property that can very naturally assume responsibility for the key. For example, if we assume that a &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; has an &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt; and a &lt;code class=&quot;language-text&quot;&gt;userId&lt;/code&gt;, then either the &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt; or the &lt;code class=&quot;language-text&quot;&gt;userId&lt;/code&gt; could be used as the key if they are guaranteed to be unique.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;khalil@khalilstemmler.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// highlight&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Khalil Stemmler&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;2&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                        &lt;span class=&quot;token comment&quot;&gt;// or this&lt;/span&gt;
  phone&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;555-123-4567&apos;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Other times, we&apos;re working with data where uniqueness is a little more ambiguous. Take, for example, the case of a dictionary again. Consider the dictionary definition for the word &lt;em&gt;chair&lt;/em&gt; looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  word&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;chair&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  definition&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;a separate seat for one person, typically with a back 
   and four legs.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What can we use for uniqueness here? &lt;/p&gt;
&lt;p&gt;If we wish to store this in a hash table to quickly access the dictionary definition for the word, we&apos;d have to use the word &lt;em&gt;chair&lt;/em&gt; as the key itself.&lt;/p&gt;
&lt;p&gt;However, based on this design, we cannot be sure to have uniqueness. Why? Because within the English language exists the idea of &lt;em&gt;homonyms&lt;/em&gt;: words spelled (and sometimes pronounced) the same but with different meanings.&lt;/p&gt;
&lt;p&gt;For example, there is another dictionary definition for the word &lt;em&gt;chair.&lt;/em&gt; &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  word&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;chair&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  definition&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;the person in charge of a meeting or of an organization 
   (used as a neutral alternative to chairman or chairwoman).&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See the problem here? If we merely use &lt;code class=&quot;language-text&quot;&gt;word&lt;/code&gt; as the key, then we cannot be sure it&apos;s unique. And uniqueness is important for retrieval to get access to the definition by providing the word. If we have two definitions for the same word, this probably has to influence how we shape our data.&lt;/p&gt;
&lt;p&gt;We could solve this problem by changing how we choose to model our data.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  word&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;chair&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  definition&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;a separate seat for one person, typically with a back 
	   and four legs.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;the person in charge of a meeting or of an organization 
	   (used as a neutral alternative to chairman or chairwoman).&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we wanted, it also wouldn’t hurt to improve the data structure even more by giving each definition a &lt;code class=&quot;language-text&quot;&gt;type&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;example&lt;/code&gt; property. This means that the data we store within the definition array would actually need to become an object.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  word&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;chair&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// the key to all of this data&lt;/span&gt;&lt;/span&gt;  definition&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
      &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;noun&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      example&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;no one occupied the seat, so I sat in it&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;a separate seat for one person, typically with a back 
        and four legs.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;noun&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      example&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;a three-year term as the board’s deputy chair&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;the person in charge of a meeting or of an organization 
        (used as a neutral alternative to chairman or chairwoman).&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Great, so we have some data which can be uniquely identified, and we have some data that we’d like to store so that we can retrieve quickly. &lt;/p&gt;
&lt;h3 id=&quot;Hash-functions&quot; style=&quot;position:relative;&quot;&gt;Hash functions&lt;a href=&quot;#Hash-functions&quot; aria-label=&quot;Hash functions permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once we have the key-value pair, we pass them to the hash table to store the data for later retrieval. Hash tables need a hash function to determine how the table should store the data, and this is one of the standard hash table operations.&lt;/p&gt;
&lt;p&gt;The hash function requires both key and the value. &lt;/p&gt;
&lt;p&gt;The key contains the logic that determines what &lt;em&gt;index&lt;/em&gt; the value will live at within the underlying data structure (array or object).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When we use objects as storage, the index is often just some string or integer version of the key.&lt;/li&gt;
&lt;li&gt;When we&apos;re a fixed-size array as storage, we need to generate a &lt;strong&gt;hash code: a value that maps the key to a valid index/position in the array&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After deciding on an index, depending on how we&apos;ve implemented it, the hash function can insert or merge the value at the position specified by the index.&lt;/p&gt;
&lt;p&gt;For example, suppose our dictionary hash table had saved only one of the possible definitions for the word &lt;em&gt;chair&lt;/em&gt; so far. In that case, we could configure the hash function to merge additional non-duplicate definitions to the &lt;em&gt;chair&lt;/em&gt; value&apos;s definition when we try to hash it.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;diff&quot;&gt;&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;{
&lt;span class=&quot;token unchanged&quot;&gt;  &apos;cat&apos;: [...],
  &apos;chai&apos;: [...],
&lt;/span&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;- &apos;chair&apos;: { 
-    type: &apos;noun&apos;,
-    example: &apos;no one occupied the seat, so I sat in it&apos;,
-    value: `a separate seat for one person, typically with a back 
-      and four legs.`,
-  }
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;+ &apos;chair&apos;: [
+    { 
+     type: &apos;noun&apos;,
+     example: &apos;no one occupied the seat, so I sat in it&apos;,
+     value: `a separate seat for one person, typically with a back 
+	      and four legs.`,
+    }, 
+    {
+     type: &apos;noun&apos;,
+	  example: &apos;a three-year term as the board’s deputy chair&apos;,
+     value: `the person in charge of a meeting or of an organization 
+	      (used as a neutral alternative to chairman or chairwoman).`
+    }
+  ]
&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Alternatively, we could also configure it to throw an error if the hash function encounters a duplicate. In implementations where we&apos;re not merging data, this is generally referred to as a collision.&lt;/p&gt;
&lt;h3 id=&quot;Methodsoperations-what-can-it-do&quot; style=&quot;position:relative;&quot;&gt;Methods/operations (what can it do?)&lt;a href=&quot;#Methodsoperations-what-can-it-do&quot; aria-label=&quot;Methodsoperations what can it do permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We know that one of the operations a hash table should perform is to &lt;em&gt;hash&lt;/em&gt; an item — that is, to create the unique index based on a key. What other things should it be capable of?&lt;/p&gt;
&lt;p&gt;At the bare minimum, a hash table should be able to perform:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;add — add a key-value pair&lt;/li&gt;
&lt;li&gt;get — get a value by key&lt;/li&gt;
&lt;li&gt;remove — remove a value by key&lt;/li&gt;
&lt;li&gt;list — get all the keys (or key-value pairs)&lt;/li&gt;
&lt;li&gt;count — count the number of items in the table&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;How-to-choose-the-key-in-a-hash-table&quot; style=&quot;position:relative;&quot;&gt;How to choose the key in a hash table&lt;a href=&quot;#How-to-choose-the-key-in-a-hash-table&quot; aria-label=&quot;How to choose the key in a hash table permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To determine what should be the key in the key-value pair, it must be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unique (e.g., &lt;em&gt;yellow&lt;/em&gt; is a unique word — and though it has many definitions, we can store those definitions at the index created by the &lt;em&gt;yellow&lt;/em&gt; key).&lt;/li&gt;
&lt;li&gt;known by the client in the world so that data can be re-retrieved (e.g., in storing the value, we must remember the key to re-retrieve it in constant time)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Basic-JavaScript-hash-table-examples&quot; style=&quot;position:relative;&quot;&gt;Basic JavaScript hash table examples&lt;a href=&quot;#Basic-JavaScript-hash-table-examples&quot; aria-label=&quot;Basic JavaScript hash table examples permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this section, we’ll look at various ways to implement hash tables using JavaScript (and TypeScript). There are differences in languages like Java and Python (for example, in Java, you can use the HashMap interface as a part of the Java collection package). Still, ultimately, most general-purpose languages have a few different ways to implement a hash table.&lt;/p&gt;
&lt;p&gt;Let&apos;s start with the simplest one.&lt;/p&gt;
&lt;h3 id=&quot;Object-implementation&quot; style=&quot;position:relative;&quot;&gt;Object implementation&lt;a href=&quot;#Object-implementation&quot; aria-label=&quot;Object implementation permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The object implementation of a hash table in JavaScript is to merely lean on the usage of the plain ol&apos; JavaScript object.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; table &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are a few ways the API allows us to add a key-value pair to our table. The first is to use the dot-property.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; table &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
table&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;yellow &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;color between green and orange&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// { yellow: &apos;color between green and orange&apos; }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Another way is to use object brackets (which is useful when our key is numeric).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; table &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; pairOne &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; key&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;yellow&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;color between green and orange&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; pairTwo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; key&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Bob&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Text key&lt;/span&gt;
table&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;pairOne&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pairOne&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// { yellow: &apos;color between green and orange&apos; }&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Numeric key&lt;/span&gt;
table&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;pairTwo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pairTwo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value 
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// { &lt;/span&gt;
                    &lt;span class=&quot;token comment&quot;&gt;//    yellow: &apos;color between green and orange&apos;, &lt;/span&gt;
                    &lt;span class=&quot;token comment&quot;&gt;//    2: { name: &apos;Bob&apos; } &lt;/span&gt;
                    &lt;span class=&quot;token comment&quot;&gt;//  }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To see if a value is present, we can use the &lt;code class=&quot;language-text&quot;&gt;hasOwnProperty&lt;/code&gt; method that’s a part of every object in JavaScript.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; table &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
table&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;yellow &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;color between green and orange&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

table&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;yellow&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To get the value of an item, we can call upon it using the key within either object brackets or with object dot notation.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; table &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
table&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;yellow &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;color between green and orange&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;yellow&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &apos;color between green and orange&apos;&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;yellow&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// &apos;color between green and orange&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When you&apos;re solving one-off algorithmic problems, you can use objects to get the functionality you need from a hash table quickly. However, there are better ways to design hash tables to be easier to use, and one such route is through encapsulation.&lt;/p&gt;
&lt;h3 id=&quot;Encapsulated-hash-table&quot; style=&quot;position:relative;&quot;&gt;Encapsulated hash table&lt;a href=&quot;#Encapsulated-hash-table&quot; aria-label=&quot;Encapsulated hash table permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When you have related functionality, it&apos;s generally a good idea to encapsulate it within a cohesive object or a collection of functions. Here, we create a &lt;code class=&quot;language-text&quot;&gt;HashTable&lt;/code&gt; class that uses a plain object for storage and exposes all the necessary methods for a hash table.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HashTable&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;storage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Hash function&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;key&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; already exists&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;storage&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;key&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; not found&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;storage&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;storage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;storage&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;storage&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;storage&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;storage&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; hashTable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HashTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
hashTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bill&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
hashTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Mary&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
hashTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Samson&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;The hashtable has &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;hashTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; elements&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;This is &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;hashTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

hashTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;The hashtable has &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;hashTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; elements&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Here are all the elements: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;hashTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The console output would look like the following:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;The hashtable has &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; elements
This &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; Mary
The hashtable has &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; elements
Here are all the elements&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;object Object&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;object Object&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Other-similar-data-structures&quot; style=&quot;position:relative;&quot;&gt;Other similar data structures&lt;a href=&quot;#Other-similar-data-structures&quot; aria-label=&quot;Other similar data structures permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Lots of languages have hash table-like data structures already defined into the language. &lt;/p&gt;
&lt;p&gt;You may hear about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html&quot;&gt;Hashmaps&lt;/a&gt; (Java)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map&quot;&gt;Maps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set&quot;&gt;Sets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/python/python_dictionaries.asp&quot;&gt;Dictionaries&lt;/a&gt; (Python)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each of these are (more or less) the same thing as a hash table.&lt;/p&gt;
&lt;h2 id=&quot;Associative-array-JavaScript-hash-table-example-advanced&quot; style=&quot;position:relative;&quot;&gt;Associative array JavaScript hash table example (advanced)&lt;a href=&quot;#Associative-array-JavaScript-hash-table-example-advanced&quot; aria-label=&quot;Associative array JavaScript hash table example advanced permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&apos;s now look at a more advanced way to create hash tables using arrays as the backing data structure instead of objects.&lt;/p&gt;
&lt;p&gt;We create a &lt;code class=&quot;language-text&quot;&gt;HashTable&lt;/code&gt; class and initialize a fixed-size array to 200 elements.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HashTable&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;table &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Hash-code&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Hash code&lt;/strong&gt;&lt;a href=&quot;#Hash-code&quot; aria-label=&quot;Hash code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Next, let&apos;s implement the &lt;code class=&quot;language-text&quot;&gt;hash&lt;/code&gt; method. Assuming this is a private method used by all of the other public methods, its job is to create a hash code from a key.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;hash code is a value computed from the key&lt;/strong&gt; which &lt;strong&gt;designates the index&lt;/strong&gt; which the value should be saved at within the array.&lt;/p&gt;
&lt;p&gt;In this implementation, the hash function expects a &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; key and returns a numeric hash code. Looking at each element in the string, we add the character codes to create a hash code.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Assume the key is a &apos;string&apos;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;_hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; hash &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    hash &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;charCodeAt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; hash&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But how can we make sure that the hash value stays within the bounds of the array? One solution is to use the modulo operator to have the number roll around and never surpass the table length.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token function&quot;&gt;_hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; hash &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    hash &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;charCodeAt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; hash &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Implementing-the-operations&quot; style=&quot;position:relative;&quot;&gt;Implementing the operations&lt;a href=&quot;#Implementing-the-operations&quot; aria-label=&quot;Implementing the operations permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Within the &lt;code class=&quot;language-text&quot;&gt;add&lt;/code&gt; method, we create a hash code to use as an index, and then we store both the key and the value within the array. We also increment the array size so we can tell how fully utilized the array storage is. We may want to resize it later when we get to a decent size utilization.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For the &lt;code class=&quot;language-text&quot;&gt;get&lt;/code&gt; method, we&apos;ll rely on the hash function again to get the index for the value.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then to &lt;code class=&quot;language-text&quot;&gt;remove&lt;/code&gt; an item, we merely remove the item from the array and decrement the size counter.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token function&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; itemExists &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;itemExists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A full associative array hash table implementation looks like the following:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HashTable&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;table &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;_hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; hash &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      hash &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;charCodeAt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; hash &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; target &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; itemExists &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;itemExists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;table&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let’s go ahead and test it out now.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ht &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HashTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Bill&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;519-429-2212&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Kit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;647-232-1246&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Susan&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;754-664-2397&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Bill&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [ &apos;Bill&apos;, &apos;519-429-2212&apos; ]&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Kit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [ &apos;Kit&apos;, &apos;647-232-1246&apos; ]&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Susan&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [ &apos;Susan&apos;, &apos;754-664-2397&apos; ]&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Kit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Kit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// undefined&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Looks good! If we were also to inspect the console afterward, here’s what the table could look like. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/data-structures/hash-tables/hash-table-javascript.png&quot; alt=&quot;JavaScript Hash Table&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Collisions&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Collisions&lt;/strong&gt;&lt;a href=&quot;#Collisions&quot; aria-label=&quot;Collisions permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A collision is when the &lt;strong&gt;hash function&lt;/strong&gt; maps two or more key-value pair to the &lt;strong&gt;same storage index&lt;/strong&gt;. As we populate the array, we’re bound to run into scenarios where collisions occur. &lt;/p&gt;
&lt;p&gt;For example, if we were to run the following, we’d end up with a collision.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ht &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HashTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Susan&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;754-664-2397&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;555-123-5555&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Susan&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [&apos;z&apos;, &apos;555-123-5555&apos;]&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;// [&apos;z&apos;, &apos;555-123-5555&apos;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It appears we’ve overridden the “Susan” key with the “z”. This is very bad because it means we’ve lost data. And we don’t want that.&lt;/p&gt;
&lt;p&gt;How does this even happen? Well, the reason why this happened is because the ASCII character for “z” is equal to the added ASCII characters in “Susan”. It’s &lt;code class=&quot;language-text&quot;&gt;122&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To fix this, we’ll need collision detection (and optionally, array resizing) logic.&lt;/p&gt;
&lt;h3 id=&quot;Collision-detection-and-dynamic-array-resizing&quot; style=&quot;position:relative;&quot;&gt;Collision detection and dynamic array resizing&lt;a href=&quot;#Collision-detection-and-dynamic-array-resizing&quot; aria-label=&quot;Collision detection and dynamic array resizing permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It turns out that this is quite a challenging problem to solve. There are trivial approaches like just storing the same data in the same array index position and then merely traversing through it, but that increases the time complexity to O(n).
As you&apos;ll discover down the road of writing your own hash table with associative arrays, there is no perfect approach to collision detection and dynamic array resizing.&lt;/p&gt;
&lt;p&gt;There is one easy thing we can do, however. Using a prime number for the array (like &lt;code class=&quot;language-text&quot;&gt;257&lt;/code&gt;, for example), we drastically reduce the likelihood of a collision.&lt;/p&gt;
&lt;p&gt;If we had set the array size to &lt;code class=&quot;language-text&quot;&gt;257&lt;/code&gt; instead of &lt;code class=&quot;language-text&quot;&gt;200&lt;/code&gt;, we’d get:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ht &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HashTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Susan&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;754-664-2397&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;555-123-5555&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Susan&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [&apos;Susan&apos;, &apos;754-664-2397&apos;]&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ht&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;// [&apos;z&apos;, &apos;555-123-5555&apos;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/data-structures/hash-tables/hash-table-javascript-collision.png&quot; alt=&quot;hash-table-javascript-collision&quot;&gt;&lt;/p&gt;
&lt;p&gt;One technique for collision detection and resizing is called &lt;strong&gt;Prime Double Hash Table&lt;/strong&gt; and it relies on the use of one smaller and one larger hash table. &lt;a href=&quot;https://web.archive.org/web/19990903133921/http://www.concentric.net/~Ttwang/tech/primehash.htm&quot;&gt;You can read here for more information on how this works&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Which-implementation-should-I-use&quot; style=&quot;position:relative;&quot;&gt;Which implementation should I use?&lt;a href=&quot;#Which-implementation-should-I-use&quot; aria-label=&quot;Which implementation should I use permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For simplicity, &lt;strong&gt;I generally advocate you use one of the language&apos;s hash tables&lt;/strong&gt; &lt;strong&gt;or&lt;/strong&gt; &lt;strong&gt;encapsulate an object for storage&lt;/strong&gt; instead of rolling your own associate array style hash table. Dealing with collisions and resizing is messy, and there are other more important things you need to spend your time coding.&lt;/p&gt;
&lt;h2 id=&quot;When-to-use-hash-tables-use-cases&quot; style=&quot;position:relative;&quot;&gt;When to use hash tables (use cases)&lt;a href=&quot;#When-to-use-hash-tables-use-cases&quot; aria-label=&quot;When to use hash tables use cases permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Not only are hash tables one of the first types of data structures you should reach for when solving problems in programming interviews, but their fast retrieval time makes them great for a variety of other use cases. Here are some common ones.&lt;/p&gt;
&lt;h3 id=&quot;Databases-indexing&quot; style=&quot;position:relative;&quot;&gt;Databases (indexing)&lt;a href=&quot;#Databases-indexing&quot; aria-label=&quot;Databases indexing permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Probably the most common use for hash tables is databases. To retrieve and increment through data in a database in a performant way, we need some way to identify it uniquely, and we need some way to index it.&lt;/p&gt;
&lt;p&gt;In databases, we use indexes to locate data fast without needing to search through every single row. If a database has records from 0 to 100 and it knows that we&apos;re looking for 88, it doesn&apos;t need to start from 0 and traverse up to 88. It can begin the search from a much closer index.&lt;/p&gt;
&lt;h3 id=&quot;Caching-backend&quot; style=&quot;position:relative;&quot;&gt;Caching (backend)&lt;a href=&quot;#Caching-backend&quot; aria-label=&quot;Caching backend permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Caching is a technique we use to speed up requests.&lt;/p&gt;
&lt;p&gt;We separate read-like commands from write-like ones in &lt;a href=&quot;https://khalilstemmler.com/articles/oop-design-principles/command-query-separation/#CQS-in-Domain-Driven-Design-Architecture-with-CQRS&quot;&gt;Command Query Response Segregation (CQRS)&lt;/a&gt;. We do this so that we can scale both sides independently.&lt;/p&gt;
&lt;p&gt;On the read side, if we could tell that data hasn&apos;t changed yet (there haven&apos;t been any recent write-like operations — no commands), then there&apos;s an opportunity to optimize reads to the database.&lt;/p&gt;
&lt;p&gt;In computing, reading from disk (database) takes longer than reading from memory (cache). Therefore, if we used an in-memory data store like Redis, we could speed up requests by offloading some of the reads to Redis instead.&lt;/p&gt;
&lt;p&gt;Here&apos;s a Gherkins Given-When-Then (BDD-style) story to describe what should happen.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;gherkin&quot;&gt;&lt;pre class=&quot;language-gherkin&quot;&gt;&lt;code class=&quot;language-gherkin&quot;&gt;&lt;span class=&quot;token feature&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Feature:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Caching&lt;/span&gt;

&lt;/span&gt;	&lt;span class=&quot;token scenario&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Scenario:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Cache miss &lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token atrule&quot;&gt;Given&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;a&lt;/span&gt; resource is not cached  
		&lt;span class=&quot;token atrule&quot;&gt;When&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;a&lt;/span&gt; read request comes in for the resource 
		&lt;span class=&quot;token atrule&quot;&gt;Then&lt;/span&gt; the controller fulfils the request by going to the database
		&lt;span class=&quot;token atrule&quot;&gt;And&lt;/span&gt; the controller saves the resource to the cache for the next time

	&lt;span class=&quot;token scenario&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Scenario:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Cache hit&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token atrule&quot;&gt;Given&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;a&lt;/span&gt; resource is cached
		&lt;span class=&quot;token atrule&quot;&gt;When&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;a&lt;/span&gt; read request comes in for the resource
		&lt;span class=&quot;token atrule&quot;&gt;Then&lt;/span&gt; the controller fulfils the request by going to the cache

  &lt;span class=&quot;token scenario&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Scenario:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Cache invalidation&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token atrule&quot;&gt;Given&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;a&lt;/span&gt; resource is cached
		&lt;span class=&quot;token atrule&quot;&gt;When&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;a&lt;/span&gt; write request on the resource is performed
		&lt;span class=&quot;token atrule&quot;&gt;Then&lt;/span&gt; the cache invalidates the resource by removing it from the cache
		&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Caching-front-end-state-management&quot; style=&quot;position:relative;&quot;&gt;Caching (front-end state management)&lt;a href=&quot;#Caching-front-end-state-management&quot; aria-label=&quot;Caching front end state management permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the &lt;a href=&quot;https://khalilstemmler.com/articles/client-side-architecture/layers/#%EF%B8%8F-State-management--storage-infrastructure&quot;&gt;state management layer&lt;/a&gt; of a client-side application, we often find ourselves needing to persist, remove, and update data in storage.&lt;/p&gt;
&lt;p&gt;Using tools like Apollo Client, Redux, or React hooks, the work we do to uniquely identify data and &lt;a href=&quot;https://www.apollographql.com/blog/apollo-client/caching/demystifying-cache-normalization/&quot;&gt;normalize it within our client-side cache&lt;/a&gt; is very similar to hashing function and persistence logic we write in hash tables.&lt;/p&gt;
&lt;h3 id=&quot;Finding-all-unique-elements&quot; style=&quot;position:relative;&quot;&gt;Finding all unique elements&lt;a href=&quot;#Finding-all-unique-elements&quot; aria-label=&quot;Finding all unique elements permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;One other great use for a hash table is to find all unique elements among a list or collection of unorganized data.&lt;/p&gt;
&lt;p&gt;Using some common aspects as the key, we can ensure that an item is only inserted once.
Once that&apos;s done, we can merely iterate through the keys to get the entirety of the hash table&apos;s unique items.&lt;/p&gt;
&lt;p&gt;Hash tables are a prevalent technique used in algorithm-based interview questions. As mentioned in Cracking the Coding Interview, hash tables should be one of the first data structures that come to mind for solving a potential challenge.&lt;/p&gt;
&lt;h3 id=&quot;Storing-transitions-transposition-table&quot; style=&quot;position:relative;&quot;&gt;Storing transitions (transposition table)&lt;a href=&quot;#Storing-transitions-transposition-table&quot; aria-label=&quot;Storing transitions transposition table permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This one is cool. Think about chess or other games where it may be essential to keep track of the entire sequence of moves made.&lt;/p&gt;
&lt;p&gt;We can figure out any move&apos;s previous move in constant (O(1)) time with a transposition table.
Assume a player&apos;s piece is at [1, 3]. How can we know what the previous move was? If we store moves like [xPosition, yPosition, moveNumber, player], we can use that as a key that maps to the previous position as a value.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[1, 3, 5, 1] → [1, 4, 4, 1]&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This says that player 1 is now at position [1, 3] as their 5th move. It also says that before their 5th move (their 4th), they were at [1, 4].&lt;/p&gt;
&lt;p&gt;To retrieve the previous move, the hash function could easily find the index based on the player&apos;s piece&apos;s current position and the turn number. This is just an example; of course, there may be better ways to do this, but it should further illustrate the power of hash tables.&lt;/p&gt;
&lt;p&gt;To learn more, &lt;a href=&quot;https://en.wikipedia.org/wiki/Transposition_table&quot;&gt;read about transposition tables here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;FAQ&quot; style=&quot;position:relative;&quot;&gt;FAQ&lt;a href=&quot;#FAQ&quot; aria-label=&quot;FAQ permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Hashtable-vs-hashmap--whats-the-difference&quot; style=&quot;position:relative;&quot;&gt;Hashtable vs. hashmap — what’s the difference?&lt;a href=&quot;#Hashtable-vs-hashmap--whats-the-difference&quot; aria-label=&quot;Hashtable vs hashmap  whats the difference permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Hash tables and hash maps are essentially the same things, and it just comes down to the methods you use and what you choose to use as your backing data structure.&lt;/p&gt;
&lt;p&gt;People typically equate the idea of a hash table with that of the associative array approach. But people often associate the idea of a HashMap with the object approach.&lt;/p&gt;
&lt;p&gt;Right? They do the same thing and ideally have the same time complexity, but it comes down to the methods and storage.&lt;/p&gt;
&lt;h3 id=&quot;How-do-you-create-a-hashmap-in-JavaScript&quot; style=&quot;position:relative;&quot;&gt;How do you create a hashmap in JavaScript?&lt;a href=&quot;#How-do-you-create-a-hashmap-in-JavaScript&quot; aria-label=&quot;How do you create a hashmap in JavaScript permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We technically already did this with the object implementation example we first explored in this article. HashMaps are a specific type of data structure that exists in Java but (and hackily in JavaScript).&lt;/p&gt;
&lt;p&gt;Without a HashMap abstraction, we can achieve similar behavior like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createHashCode&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; obj&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;someUniqueKey&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Just an example&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; dict &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

dict&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; obj1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
dict&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; obj2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There is, however, the &lt;code class=&quot;language-text&quot;&gt;Map&lt;/code&gt; abstraction in JavaScript.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; map &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; obj1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; obj2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; obj1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; obj2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// expected output: { value: 1 }&lt;/span&gt;

map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;billy&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// expected output: { value: &apos;billy&apos; }&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// expected output: 3&lt;/span&gt;

map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// expected output: 2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Summary&quot; style=&quot;position:relative;&quot;&gt;Summary&lt;a href=&quot;#Summary&quot; aria-label=&quot;Summary permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this article, we learned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;That hash tables an abstract data structure that stores data in key-value pairs and can be used for fast data retrieval&lt;/li&gt;
&lt;li&gt;Hash tables can be implemented to have either an object or an array as the backing storage structure&lt;/li&gt;
&lt;li&gt;A key must be unique and readily queryable by the client&lt;/li&gt;
&lt;li&gt;The object implementation of a hash table is perhaps the simplest but languages like Java, Python, and TypeScript also have their own language-defined implementations of hash tables which can be used instead of rolling your own&lt;/li&gt;
&lt;li&gt;If using an array for the backing data storage of a hash table, one must be ready to perform collision detection and dynamic array resizing logic&lt;/li&gt;
&lt;li&gt;Hash tables are a common data structure in software engineering. They can be found or influenced in the design and implementation of databases, caching strategies, and more.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[When to Use TypeScript Abstract Classes]]></title><description><![CDATA[If you're just getting started with object-oriented programming, the notion of an  class may seem a little foreign. Abstraction is one of…]]></description><link>https://khalilstemmler.com/blogs/typescript/abstract-class/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/typescript/abstract-class/</guid><pubDate>Sun, 09 Jan 2022 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;If you&apos;re just getting started with object-oriented programming, the notion of an &lt;code class=&quot;language-text&quot;&gt;abstract&lt;/code&gt; class may seem a little foreign. Abstraction is one of the key ideas from object-oriented programming, and abstract classes are one of the two tools that OO provides to implement abstraction.&lt;/p&gt;
&lt;p&gt;In this article, we&apos;ll learn all about abstraction, abstract classes, and everyday use cases for using them in your projects.&lt;/p&gt;
&lt;p&gt;Let&apos;s start by understanding abstraction: perhaps the most crucial concept from object-oriented programming.&lt;/p&gt;
&lt;h2 id=&quot;What-is-abstraction&quot; style=&quot;position:relative;&quot;&gt;What is abstraction?&lt;a href=&quot;#What-is-abstraction&quot; aria-label=&quot;What is abstraction permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/object-oriented/programming/4-principles/#Abstraction&quot;&gt;Abstraction&lt;/a&gt; is perhaps the most important element of design.&lt;/p&gt;
&lt;p&gt;By selectively choosing which details to include, we can make concepts appear less complex, increase understandability, communicativeness, readability, and so on.&lt;/p&gt;
&lt;p&gt;As programmers, we rely on abstraction to solve advanced architectural challenges. Abstraction removes the need to implement all the low-level details upfront; instead, we can focus on the high-level and figure out the specifics later.&lt;/p&gt;
&lt;p&gt;You could also say that abstraction allows us to spend more time on the declarative (asking for what we want) and less on the imperative (specifying exactly &lt;em&gt;how&lt;/em&gt; it&apos;ll work).&lt;/p&gt;
&lt;h3 id=&quot;Concretions--contracts&quot; style=&quot;position:relative;&quot;&gt;Concretions &amp;#x26; contracts&lt;a href=&quot;#Concretions--contracts&quot; aria-label=&quot;Concretions  contracts permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We deal primarily with two types of classes in object-oriented programming languages: concretions and contracts.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/contract/contract-concretion.png&quot; alt=&quot;Abstract vs. concretion&quot;&gt;&lt;/p&gt;
&lt;p&gt;Concrete classes are real, and we can construct objects from them to use at runtime using the &lt;code class=&quot;language-text&quot;&gt;new&lt;/code&gt; keyword.
They&apos;re what most of us end up using when we first start learning object-oriented programming.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Concrete class&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getName&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Khalil&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Creating an instance &lt;/span&gt;
                                 &lt;span class=&quot;token comment&quot;&gt;// of a concrete class&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On the other hand, contracts are &lt;em&gt;blueprints&lt;/em&gt; that specify the properties and methods that a concretion &lt;em&gt;should have&lt;/em&gt; if we want to create one from it. We can use them to contractualize the valid structure of an object or a class.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Interface (abstraction)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Box&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  length&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  width&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; boxOne&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Box &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; length&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; width&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ Valid! Has all props&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; boxTwo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Box &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; length&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;           &lt;span class=&quot;token comment&quot;&gt;// ❌ Not valid, missing prop&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Interface (abstraction)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Box&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  length&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  width&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Concrete class implementing Box abstraction&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MobileBox&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Box&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ Valid! Implements all necessary props&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; length&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; width&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;length&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; width&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; width&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; boxThree &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MobileBox&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;How-to-create-contracts-in-OO-languages&quot; style=&quot;position:relative;&quot;&gt;How to create contracts in OO languages&lt;a href=&quot;#How-to-create-contracts-in-OO-languages&quot; aria-label=&quot;How to create contracts in OO languages permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the previous examples, we used the &lt;code class=&quot;language-text&quot;&gt;interface&lt;/code&gt; keyword to create contracts. However, when we speak of contracts in object-oriented programming, we&apos;re generally referring to one of two tools:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;interfaces (i.e.: the &lt;code class=&quot;language-text&quot;&gt;interface&lt;/code&gt; keyword) or&lt;/li&gt;
&lt;li&gt;abstract classes (i.e.: the &lt;code class=&quot;language-text&quot;&gt;abstract&lt;/code&gt; keyword in front of a class)&lt;/li&gt;
&lt;/ul&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Type systems as a contract tool:&lt;/b&gt; We should also note that we can use types to implement contracts if we use a language with a type system (such as TypeScript).&lt;/p&gt;
&lt;h3 id=&quot;Why-are-contracts-necessary&quot; style=&quot;position:relative;&quot;&gt;Why are contracts necessary?&lt;a href=&quot;#Why-are-contracts-necessary&quot; aria-label=&quot;Why are contracts necessary permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Perhaps the most foundational ideas are that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you are always &lt;a href=&quot;https://khalilstemmler.com/letters/divergence-convergence-spaghetti-code/&quot;&gt;diverging or converging&lt;/a&gt; when you work&lt;/li&gt;
&lt;li&gt;in solving any problem, you always have to utilize a bit of &lt;strong&gt;upfront (convergent)&lt;/strong&gt; design and a bit of &lt;strong&gt;emergent (divergent)&lt;/strong&gt; design&lt;/li&gt;
&lt;li&gt;contracts are the tool we use to keep these two worlds in sync&lt;/li&gt;
&lt;li&gt;we use contracts to cross architectural boundaries, synchronize components... &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are so many powerful things we can use contracts to do.&lt;/p&gt;
&lt;p&gt;So many problems we can solve.&lt;/p&gt;
&lt;p&gt;A key one is that it allows us to create a plugin architecture, separating the high-level from the low-level.&lt;/p&gt;
&lt;p&gt;In traditional structured programming, we couldn&apos;t safely implement what&apos;s known as &lt;em&gt;dynamic binding&lt;/em&gt; — the ability to refer to a contract (something that doesn&apos;t concretely exist) and feel confident that the dependency would work with our code.&lt;/p&gt;
&lt;p&gt;For example, imagine we were writing the code for an OS that made USB ports work. We’d need to ensure that every device plugged in can function and do its job, but in reality, there are a &lt;em&gt;lot&lt;/em&gt; of different things that can be plugged in. What should we do? Write some code for each and every single one of those?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;deviceType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;MOUSE&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;mouseSubroutine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;HEADPHONES&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;headphonesSubroutine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;MIDI_KEYBOARD&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;midiKeyboardSubroutine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;WEBCAM&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;webcamSubroutine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That won&apos;t scale. What happens when there&apos;s a new type of USB device? Come in and write &lt;em&gt;more code&lt;/em&gt;? No, this is &lt;em&gt;architecturally&lt;/em&gt; poor. Without contracts, we&apos;d continue to increase the complexity of our USB port code as we add support for more devices over time. We&apos;d see our simple program blow up into an enormous and ever-growing control-flow graph of subroutines on subroutines.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/typescript/abstract-class/program-flow.png&quot; alt=&quot;Program flow&quot;&gt;&lt;/p&gt;
&lt;p&gt;What if there was a way to invert this dependency relationship? What if we could focus on defining a contract containing all the necessary things that a USB device needs to provide if they want it to work with the OS — and leave it to future USB device developers to implement them?&lt;/p&gt;
&lt;p&gt;We are asking: what if we could &lt;strong&gt;program against an contract instead of an implementation (a concretion)?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We can! &lt;/p&gt;
&lt;p&gt;This is the idea of &lt;em&gt;ports&lt;/em&gt; and &lt;em&gt;adapters&lt;/em&gt;. It&apos;s probably the simplest way to understand this phenomenon. Consider the contract as the &lt;em&gt;port&lt;/em&gt;. It defines a what a valid adapter is. With this design, we create a plugin architecture. This removes the need for us to need to define &lt;em&gt;every single last USB device&lt;/em&gt; and leave it to future developers to implement compatible &lt;em&gt;adapters&lt;/em&gt; based on our contract.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/typescript/abstract-class/ports-and-adapters.svg&quot; alt=&quot;ports-and-adapters&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;special-quote&quot;&gt;
&lt;p&gt;Abstraction is deeply related to the ideas of:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/solid-principles/solid-typescript/&quot;&gt;Liskov Substitution Principle&lt;/a&gt; — since we define valid subtypes, each implementation should work and be interchangeable as long as it implements the contract.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;Dependency Inversion&lt;/a&gt; — we do not directly depend on the concretions; instead, we rely on the abstraction that the concretions depend on; this keeps our core code unit testable.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;Inversion of Control&lt;/a&gt; — we can give the client developer the ability to customize behavior by inverting program control to the client developer at hook points.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;br/&gt;
&lt;p&gt;Next, let&apos;s take a look at the mechanics behind creating and using abstract classes in TypeScript.&lt;/p&gt;
&lt;h2 id=&quot;Abstract-class-in-TypeScript&quot; style=&quot;position:relative;&quot;&gt;Abstract class in TypeScript&lt;a href=&quot;#Abstract-class-in-TypeScript&quot; aria-label=&quot;Abstract class in TypeScript permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The most common use of abstract classes in TypeScript is to locate some common behavior to share within related subclasses. However, it&apos;s essential to know that you cannot instantiate an abstract class. Therefore, the only way to access shared behavior is to extend the &lt;code class=&quot;language-text&quot;&gt;abstract&lt;/code&gt; class with a subclass.&lt;/p&gt;
&lt;p&gt;For a simple demonstration, we&apos;ll imagine that we&apos;re selling digital books (&lt;code class=&quot;language-text&quot;&gt;PDF&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;EPUB&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Kindle&lt;/code&gt;, etc.) — all of which have some common logic and their specific logic as well. To start, we&apos;ll build the base &lt;code class=&quot;language-text&quot;&gt;Book&lt;/code&gt; contract to put the common logic.&lt;/p&gt;
&lt;p&gt;To declare an abstract class, we use the &lt;code class=&quot;language-text&quot;&gt;abstract&lt;/code&gt; keyword.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;token comment&quot;&gt;// .. &lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Defining-common-properties&quot; style=&quot;position:relative;&quot;&gt;Defining common properties&lt;a href=&quot;#Defining-common-properties&quot; aria-label=&quot;Defining common properties permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Within this &lt;code class=&quot;language-text&quot;&gt;Book&lt;/code&gt; abstract class, we can then decide on the contract for a &lt;code class=&quot;language-text&quot;&gt;Book&lt;/code&gt;. Let us say that all &lt;code class=&quot;language-text&quot;&gt;Book&lt;/code&gt; subclasses must have &lt;code class=&quot;language-text&quot;&gt;author&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;title&lt;/code&gt; properties. We can define them as instance variables and accept them as input using the abstract class constructor. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; author&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;  
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;author&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;author &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; author&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Defining-common-logic&quot; style=&quot;position:relative;&quot;&gt;Defining common logic&lt;a href=&quot;#Defining-common-logic&quot; aria-label=&quot;Defining common logic permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We can then can place some of the common logic within the &lt;code class=&quot;language-text&quot;&gt;Book&lt;/code&gt; abstract class using regular methods. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; author&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;author&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;author &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; author&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Common methods&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getBookTitle&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getBookAuthor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Remember that an &lt;code class=&quot;language-text&quot;&gt;abstract&lt;/code&gt; class is still a contract, after all. &lt;/p&gt;
&lt;p&gt;Even though it &lt;em&gt;looks like a class&lt;/em&gt;, really, it&apos;s &lt;em&gt;mostly&lt;/em&gt; comparable to an &lt;code class=&quot;language-text&quot;&gt;interface&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;That means we can&apos;t instantiate contracts directly (because they don&apos;t really exist, they&apos;re theoretical).&lt;/p&gt;
&lt;p&gt;Sure, we&apos;re putting some logic on the &lt;code class=&quot;language-text&quot;&gt;abstract&lt;/code&gt; class, and this is what makes it special and unique from an interface...&lt;/p&gt;
&lt;p&gt;Imagine &lt;em&gt;levels of &lt;strong&gt;realness&lt;/strong&gt;&lt;/em&gt;. You&apos;d have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;interfaces/types = least real / theoretical (defines the &apos;what&apos;)&lt;/li&gt;
&lt;li&gt;abstract classes = midpoint (can define some of the &apos;how&apos;, but can&apos;t create)&lt;/li&gt;
&lt;li&gt;(concrete) classes = completely real, defines the &apos;how&apos;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Trying anyway for demonstration purposes, you&apos;d notice that we&apos;d we get an error that looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; book &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;          &lt;span class=&quot;token comment&quot;&gt;// ❌ error TS2511: Cannot create an &lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&apos;Robert Greene&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;             &lt;span class=&quot;token comment&quot;&gt;// instance of an abstract class. &lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&apos;The Laws of Human Nature&apos;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So then, what shall we do? We&apos;ll introduce one of our specific types of &lt;code class=&quot;language-text&quot;&gt;Book&lt;/code&gt; &lt;em&gt;concretions&lt;/em&gt; — the &lt;code class=&quot;language-text&quot;&gt;PDF&lt;/code&gt; class. We extend/inherit the abstract &lt;code class=&quot;language-text&quot;&gt;Book&lt;/code&gt; class as a new subclass to hook it up.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PDF&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Extends the abstraction&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; belongsToEmail&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;author&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; belongsToEmail&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;author&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Must call super on subclass&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;belongsToEmail &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; belongsToEmail&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since &lt;code class=&quot;language-text&quot;&gt;PDF&lt;/code&gt; is a concrete class, we can instantiate it. The &lt;code class=&quot;language-text&quot;&gt;PDF&lt;/code&gt; object has all of the properties and methods of the &lt;code class=&quot;language-text&quot;&gt;Book&lt;/code&gt; abstraction, so we can call &lt;code class=&quot;language-text&quot;&gt;getBookTitle&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;getBookAuthor&lt;/code&gt; as if it were originally declared on the &lt;code class=&quot;language-text&quot;&gt;PDF&lt;/code&gt; class.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; book&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PDF&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PDF&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&apos;Robert Greene&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
	&lt;span class=&quot;token string&quot;&gt;&apos;The Laws of Human Nature&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
	&lt;span class=&quot;token string&quot;&gt;&apos;khalil@khalilstemmler.com&apos;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

book&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getBookTitle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// &quot;The Laws of Human Nature&quot;&lt;/span&gt;
book&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getBookAuthor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;Robert Greene&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Defining-mandatory-methods&quot; style=&quot;position:relative;&quot;&gt;Defining mandatory methods&lt;a href=&quot;#Defining-mandatory-methods&quot; aria-label=&quot;Defining mandatory methods permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Abstract classes have one last important feature: the notion of the &lt;code class=&quot;language-text&quot;&gt;abstract&lt;/code&gt; method. Abstract methods are methods that we &lt;em&gt;must&lt;/em&gt; define on any implementing subclass.&lt;/p&gt;
&lt;p&gt;In the abstract class, we define them like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; author&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;author&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;author &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; author&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getBookType&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// No implementation&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice that there is no implementation for the abstract method? That&apos;s because we implement it on the subclass.&lt;/p&gt;
&lt;p&gt;Demonstrating with the &lt;code class=&quot;language-text&quot;&gt;PDF&lt;/code&gt; and an additional &lt;code class=&quot;language-text&quot;&gt;EPUB&lt;/code&gt; subclass, we add the required abstract method to both of them.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PDF&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token function&quot;&gt;getBookType&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Must implement this&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;PDF&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EPUB&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;author&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;author&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token function&quot;&gt;getBookType&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Must implement this&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;EPUB&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Failing to implement the required abstract methods will fail to make the class &lt;em&gt;complete&lt;/em&gt; and &lt;em&gt;concrete&lt;/em&gt; — this means we&apos;ll run into errors when trying to compile our code or create instances.&lt;/p&gt;
&lt;p&gt;There are good reasons for using this technique. The best way to understand is to consider real-world scenarios. We&apos;ll explore this in the next section.&lt;/p&gt;
&lt;h2 id=&quot;Use-cases-when-to-use-abstract-classes&quot; style=&quot;position:relative;&quot;&gt;Use cases (when to use abstract classes)&lt;a href=&quot;#Use-cases-when-to-use-abstract-classes&quot; aria-label=&quot;Use cases when to use abstract classes permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that we know the mechanics behind how abstract classes work, let&apos;s talk about real-life use cases for it — scenarios you are likely to encounter.&lt;/p&gt;
&lt;p&gt;There are two primary use cases for needing to use abstract classes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Sharing common behavior and &lt;/li&gt;
&lt;li&gt;Template method pattern (framework hook methods)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;1-Sharing-common-behavior-base-HTTP-class-example&quot; style=&quot;position:relative;&quot;&gt;1. Sharing common behavior (base HTTP class example)&lt;a href=&quot;#1-Sharing-common-behavior-base-HTTP-class-example&quot; aria-label=&quot;1 Sharing common behavior base HTTP class example permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A prevalent scenario is the need to perform HTTP data-fetching logic within a front-end application that relies on multiple backend APIs endpoints.&lt;/p&gt;
&lt;p&gt;Let’s say that we definitely need to fetch data from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt; API located at &lt;a href=&quot;http://example.com/users&quot;&gt;example.com/users&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;a &lt;code class=&quot;language-text&quot;&gt;Reviews&lt;/code&gt; API located at &lt;a href=&quot;http://example.com/reviews&quot;&gt;example.com/reviews&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What’s the common logic?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Setting up an HTTP library (like &lt;a href=&quot;https://www.npmjs.com/package/axios&quot;&gt;Axios&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Setting up &lt;a href=&quot;https://axios-http.com/docs/interceptors&quot;&gt;interceptors&lt;/a&gt; to set up common refetching logic (say, like when an access token expires)&lt;/li&gt;
&lt;li&gt;Performing HTTP methods&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using an abstract class, we can define a &lt;code class=&quot;language-text&quot;&gt;BaseAPI&lt;/code&gt; as an abstraction with some of the implementation already provided.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseAPI&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; baseUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; axiosInstance&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AxiosInstance &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;baseUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;baseUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; baseUrl
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;axiosInstance &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; axios&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;enableInterceptors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;enableInterceptors&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Here&apos;s where you can define common refetching logic&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; params&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; headers&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAxiosInstance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      method&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;GET&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;baseUrl&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;url&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      params&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; params &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; params &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      headers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; headers &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; headers &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;

  protected post (url: string, params?: any, headers?: any): Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAxiosInstance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      method&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;POST&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;baseUrl&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;url&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      params&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; params &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; params &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      headers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; headers &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; headers &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
} &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here, we&apos;ve placed the low-level behavior within a &lt;code class=&quot;language-text&quot;&gt;BaseAPI&lt;/code&gt; contract. Now we can define the high-level behavior — the rich stuff — in the subclasses.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UsersAPI&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseAPI&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;http://example.com/users&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
 
  &lt;span class=&quot;token comment&quot;&gt;// High-level functionality&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getAllUsers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;users &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;  
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This pattern is widespread. &lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/data/data-sources/#example&quot;&gt;Apollo&apos;s REST DataSource API&lt;/a&gt; builds on the same abstract class approach.&lt;/p&gt;
&lt;h3 id=&quot;2-Template-method-design-pattern-front-end-libraries--frameworks-example&quot; style=&quot;position:relative;&quot;&gt;2. Template method design pattern (front-end libraries &amp;#x26; frameworks example)&lt;a href=&quot;#2-Template-method-design-pattern-front-end-libraries--frameworks-example&quot; aria-label=&quot;2 Template method design pattern front end libraries  frameworks example permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The template method design pattern (also known as the template pattern) is a behavioral design pattern that works by defining the skeleton of the algorithm in an abstract class and deferring some of the steps off to subclasses.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/typescript/abstract-class/template_method_design_pattern.svg&quot; alt=&quot;template method design pattern.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;Because it allows for customizability, the template method pattern is widespread in libraries and frameworks like Angular, Vue, or React.js.&lt;/p&gt;
&lt;p&gt;To demonstrate, let&apos;s consider older versions of React.js, the popular library for building front-end interfaces.&lt;/p&gt;
&lt;p&gt;When you create a React component using class-based components, what’s the one method you absolutely &lt;em&gt;positively&lt;/em&gt; need to implement? That’d be the &lt;code class=&quot;language-text&quot;&gt;render&lt;/code&gt; method, right?&lt;/p&gt;
&lt;p&gt;So then, a simplistic version of the &lt;code class=&quot;language-text&quot;&gt;abstract&lt;/code&gt; class for a component could look like the following:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Mandatory&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then to use it, we’d need to extend the &lt;code class=&quot;language-text&quot;&gt;Component&lt;/code&gt; contract and implement the render method.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Box&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Must implement this method&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We &lt;em&gt;need&lt;/em&gt; to implement the render method because it is a critical part of the work involved with deciding what gets created on screen. It&apos;s up to the client developer (us) to determine what HTML &amp;#x26; CSS the browser should show. The library can&apos;t decide on that for us, so we need to provide it.&lt;/p&gt;
&lt;p&gt;An &lt;code class=&quot;language-text&quot;&gt;abstract&lt;/code&gt; class is a suitable tool for this problem is because there is an algorithm running behind the scenes — an algorithm in which the &lt;code class=&quot;language-text&quot;&gt;render&lt;/code&gt; step is but a single step amongst many.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/typescript/abstract-class/react-lifecycle.png&quot; alt=&quot;react-lifecyclepng&quot;&gt;&lt;/p&gt;
&lt;p&gt;We can see that there are &lt;em&gt;three&lt;/em&gt; distinct phases to React: mounting, updating, and unmounting. React&apos;s abstract class further gives us (the client developer) the ability to customize our components by connecting the ability to &lt;em&gt;hook into&lt;/em&gt; various lifecycle events. For example, you can perform some behavior as soon as your component mounts (&lt;code class=&quot;language-text&quot;&gt;componentDidMount&lt;/code&gt;), when it updates (&lt;code class=&quot;language-text&quot;&gt;componentDidUpdate&lt;/code&gt;), and when it&apos;s about to unmount (&lt;code class=&quot;language-text&quot;&gt;componentWillUnmount&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Another vastly simplistic (and not entirely accurate or complete) depiction of what that may look like behind the scenes is like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	
	&lt;span class=&quot;token comment&quot;&gt;// Algorithm for mounting&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;componentDidMount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// The general algorithm for updating. Called when new props occur, &lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// when setState is called or when forceUpdate is called&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;onUpdate&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;componentShouldUpdate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;componentDidUpdate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;// Algorithm for unmounting&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;onUnmount&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;componentWillUnmount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Complete unmounting&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;componentDidMount&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// No implementation lifecycle method, allow the client to override&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;componentDidUpdate&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// No implementation lifecycle method, allow the client to override&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;componentWillUnmount&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// No implementation lifecycle method, allow the client to override&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;componentShouldUpdate&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Determines if the component should update&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now, a customized component subclass can &lt;em&gt;plug in&lt;/em&gt; behavior within those key lifecycle hook methods. This is the concept of &lt;a href=&quot;https://khalilstemmler.com/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;Inversion of Control&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Box&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token function&quot;&gt;componentDidMount&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// (Optional) Perform custom logic&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token function&quot;&gt;componentDidUpdate&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// (Optional) Perform custom logic&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token function&quot;&gt;componentWillUnmount&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// (Optional) Perform custom logic&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Must implement this method&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So as a framework designer, the Template Method design pattern is attractive when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You need the client to implement a step of the algorithm → &lt;strong&gt;so you make that step an abstract method&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;You want to provide the ability for clients to customize behavior at various steps of the algorithm → &lt;strong&gt;so you expose optional lifecycle methods to the client&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;In-summary&quot; style=&quot;position:relative;&quot;&gt;In summary&lt;a href=&quot;#In-summary&quot; aria-label=&quot;In summary permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Object-oriented programs contain concretions and contracts. Abstract classes are one of two ways we can implement contracts in object-oriented programming.&lt;/li&gt;
&lt;li&gt;Use abstract classes to define shared behavior or implement the Template Method pattern.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Frequently-asked-questions&quot; style=&quot;position:relative;&quot;&gt;Frequently asked questions&lt;a href=&quot;#Frequently-asked-questions&quot; aria-label=&quot;Frequently asked questions permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;What-is-an-abstract-class-constructor-for&quot; style=&quot;position:relative;&quot;&gt;What is an abstract class constructor for?&lt;a href=&quot;#What-is-an-abstract-class-constructor-for&quot; aria-label=&quot;What is an abstract class constructor for permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The abstract class constructor is used to set up properties or run other setup logic from within the abstract class so that the low-level abstract class methods can use them. We invoke the constructor by calling &lt;code class=&quot;language-text&quot;&gt;super&lt;/code&gt; on a subclass (derived class).&lt;/p&gt;
&lt;h3 id=&quot;What-does-the-abstract-method-do&quot; style=&quot;position:relative;&quot;&gt;What does the abstract method do?&lt;a href=&quot;#What-does-the-abstract-method-do&quot; aria-label=&quot;What does the abstract method do permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The abstract method exists to force clients to implement specific functionality necessary for the abstract class to work. We abstract away the exact details to a subclass.&lt;/p&gt;
&lt;h3 id=&quot;Whats-the-difference-between-an-interface-vs-abstract-class&quot; style=&quot;position:relative;&quot;&gt;What’s the difference between an interface vs. abstract class?&lt;a href=&quot;#Whats-the-difference-between-an-interface-vs-abstract-class&quot; aria-label=&quot;Whats the difference between an interface vs abstract class permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Interfaces and abstract classes are both examples of contracts in object-oriented programming. Where an interface can only define the properties and methods of an contract, an abstract class can define the properties and methods in addition some common behavior.&lt;/p&gt;
&lt;p&gt;We also use the &lt;code class=&quot;language-text&quot;&gt;implements&lt;/code&gt; keyword to inherit from an interface but use the &lt;code class=&quot;language-text&quot;&gt;extends&lt;/code&gt; keyword to perform inheritance against an &lt;code class=&quot;language-text&quot;&gt;abstract&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;When you need an contract, default to an interface (or a type in typed languages) but opt for an abstract class when you need to define common behavior or generalize an algorithm using the Template Method design pattern.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Camel Case vs. Snake Case vs. Pascal Case — Naming Conventions]]></title><description><![CDATA[The tldr Naming conventions dictate the way you write names (for methods, folders, variables and so on). The three most common are camel…]]></description><link>https://khalilstemmler.com/blogs/camel-case-snake-case-pascal-case/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/camel-case-snake-case-pascal-case/</guid><pubDate>Tue, 21 Dec 2021 15:04:10 GMT</pubDate><content:encoded>&lt;h2 id=&quot;The-tldr&quot; style=&quot;position:relative;&quot;&gt;The tldr&lt;a href=&quot;#The-tldr&quot; aria-label=&quot;The tldr permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Naming conventions dictate the way you write names (for methods, folders, variables and so on). The three most common are camel case, pascal case, and snake case.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Camel case&lt;/strong&gt; always starts out lowercase with each word delimited by a capital letter (like personOne, textUtil, thingsToDo)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pascal case&lt;/strong&gt; is similar to camel case, but the first letter is always capitalized (like PersonOne, TextUtil, ThingsToDo)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Snake case&lt;/strong&gt; means that we delimit words with an underscore (like person_one, text_util, things_to_do)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Continue reading for more information on usage best practices&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Introduction&quot; style=&quot;position:relative;&quot;&gt;Introduction&lt;a href=&quot;#Introduction&quot; aria-label=&quot;Introduction permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are many different ways to improve the maintainability of your codebase. One of the first things developers learn how to do is to decide upon and &lt;a href=&quot;https://khalilstemmler.com/blogs/tooling/enforcing-husky-precommit-hooks/&quot;&gt;enforce a set of coding conventions&lt;/a&gt; to create consistency in the formatting and style of your code. Under the umbrella of coding conventions exists the idea of &lt;em&gt;naming conventions&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Camel case, snake case, and pascal case are three of the most common types of programming language naming conventions found across all programming languages.&lt;/p&gt;
&lt;p&gt;In this article, we discuss why naming conventions matter; we look at camel case, snake case, and pascal case — and for each, we demonstrate with examples and learn when to use each in a variety of programming languages.&lt;/p&gt;
&lt;h2 id=&quot;Naming-conventions&quot; style=&quot;position:relative;&quot;&gt;Naming conventions&lt;a href=&quot;#Naming-conventions&quot; aria-label=&quot;Naming conventions permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;What-are-they&quot; style=&quot;position:relative;&quot;&gt;What are they?&lt;a href=&quot;#What-are-they&quot; aria-label=&quot;What are they permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Naming conventions are rules that dictate the way you name the various files, folders, and tokens in our code (such as variables, functions, classes, methods, objects, and so on).&lt;/p&gt;
&lt;h3 id=&quot;Naming-conventions-based-on-language&quot; style=&quot;position:relative;&quot;&gt;Naming conventions based on language&lt;a href=&quot;#Naming-conventions-based-on-language&quot; aria-label=&quot;Naming conventions based on language permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;While a team can decide upon naming conventions for any project, each programming language has standard naming conventions for different tokens.&lt;/p&gt;
&lt;p&gt;For example, in C-styled languages like Java, JavaScript, and TypeScript, while it&apos;s conventional to use the camel case convention for variables, functions, method names, and object properties, it&apos;s common practice to use the pascal case convention for classes, interfaces, and namespaces.
That&apos;s not to say that you can&apos;t use snake case or other unconventional naming conventions for a language like Java or JavaScript. In most cases, your code will still compile and run, but it&apos;s good to generally try to avoid going against the typical conventional naming practices for the language. Because there are usual language conventions, adhering to those rules can help improve the ease of future maintenance.&lt;/p&gt;
&lt;h3 id=&quot;Why-naming-conventions&quot; style=&quot;position:relative;&quot;&gt;Why naming conventions?&lt;a href=&quot;#Why-naming-conventions&quot; aria-label=&quot;Why naming conventions permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The entire idea behind naming conventions is to help make code more maintainable for the reader. By enforcing a convention and naming tokens consistently, we accomplish two things: discoverability and understanding.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Discoverability:&lt;/strong&gt; How quickly can someone find a folder, file, feature, class, or method they need to change?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Understanding:&lt;/strong&gt; How fast can someone look at our code and understand what it is they&apos;re looking at?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We want to make it very easy for developers on our team to find what they&apos;re looking for, understand what it is, and understand how to use it as quickly as possible.&lt;/p&gt;
&lt;h3 id=&quot;The-most-common-naming-conventions&quot; style=&quot;position:relative;&quot;&gt;The most common naming conventions&lt;a href=&quot;#The-most-common-naming-conventions&quot; aria-label=&quot;The most common naming conventions permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Across all programming languages, the most common naming conventions are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Camel case (ex: someVariable)&lt;/li&gt;
&lt;li&gt;Snake case (ex: some_variable)&lt;/li&gt;
&lt;li&gt;Pascal case (ex: SomeVariable)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&apos;s explore each one.&lt;/p&gt;
&lt;h2 id=&quot;Camel-case&quot; style=&quot;position:relative;&quot;&gt;Camel case&lt;a href=&quot;#Camel-case&quot; aria-label=&quot;Camel case permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/camel-snake-pascal-case/camel-case.png&quot; alt=&quot;camel-case.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Camel case is perhaps the most common naming convention of all three. A camel case word is a single or compound word that uses capital letters to make different parts of the word easier to read.&lt;/p&gt;
&lt;p&gt;It adheres to the following rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The word doesn&apos;t end on a capital letter (like someVariablE)&lt;/li&gt;
&lt;li&gt;Capital letters can only appear at the start of the second word (like someVariable). &lt;/li&gt;
&lt;li&gt;No dots, underscores, numbers, dashes, or any other special characters are allowed within the word (like som.eVar-1able)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In most C-style languages, we use camel case to denote variables, properties, attributes, methods, and functions.&lt;/p&gt;
&lt;p&gt;Some make a distinction between &lt;em&gt;lowerCaseCamel&lt;/em&gt; and &lt;em&gt;UpperCaseCamel&lt;/em&gt;, but most developers refer to the former as merely camel case and the latter as pascal case (which we&apos;ll talk about later).&lt;/p&gt;
&lt;h3 id=&quot;Camel-case-examples&quot; style=&quot;position:relative;&quot;&gt;Camel case examples&lt;a href=&quot;#Camel-case-examples&quot; aria-label=&quot;Camel case examples permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;someVariable&lt;/li&gt;
&lt;li&gt;eventDispatcher&lt;/li&gt;
&lt;li&gt;eventsRepo&lt;/li&gt;
&lt;li&gt;slackService&lt;/li&gt;
&lt;li&gt;parentComment&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Camel-case-usage-in-TypeScript&quot; style=&quot;position:relative;&quot;&gt;Camel case usage in TypeScript&lt;a href=&quot;#Camel-case-usage-in-TypeScript&quot; aria-label=&quot;Camel case usage in TypeScript permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In TypeScript &amp;#x26; JavaScript, the camel case convention is used to signify that a token is a variable, function, method, parameter, or property.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; UserProps &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;   
  firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Used to signify properties&lt;/span&gt;
  lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Serializable&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
	&lt;span class=&quot;token function&quot;&gt;toJSON&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// A method also camel cased&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Serializable&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;// Camel cased property&lt;/span&gt;
	
  &lt;span class=&quot;token comment&quot;&gt;// constructor and parameters are camel cased&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toJSON&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Variables are camel case&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userOne &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Khalil&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Stemmler&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userTwo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Nick&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Cave&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Snake-case&quot; style=&quot;position:relative;&quot;&gt;Snake case&lt;a href=&quot;#Snake-case&quot; aria-label=&quot;Snake case permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/camel-snake-pascal-case/snake_case.png&quot; alt=&quot;snake_case.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Snake case (also referred to as underscore case) is when all the letters of the word are lower case but delimited by an underscore.&lt;/p&gt;
&lt;p&gt;We seldom use the snake case coding convention in C-style languages like Java, JavaScript, and TypeScript. They&apos;re typically only used in programming languages like these to denote constants. To denote a constant, we typically implement &lt;em&gt;screaming snake case&lt;/em&gt;: snake case with all of the letters capitalized.&lt;/p&gt;
&lt;p&gt;You&apos;ll most commonly see snake case in the Python scripting language as is popularized in the &lt;a href=&quot;https://www.python.org/dev/peps/pep-0008/&quot;&gt;Python style guide&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Snake-case-examples&quot; style=&quot;position:relative;&quot;&gt;Snake case examples&lt;a href=&quot;#Snake-case-examples&quot; aria-label=&quot;Snake case examples permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;some_variable&lt;/li&gt;
&lt;li&gt;event_dispatcher&lt;/li&gt;
&lt;li&gt;events_repo&lt;/li&gt;
&lt;li&gt;slack_service&lt;/li&gt;
&lt;li&gt;parent_comment&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Snake-case-usage-in-TypeScript&quot; style=&quot;position:relative;&quot;&gt;Snake case usage in TypeScript&lt;a href=&quot;#Snake-case-usage-in-TypeScript&quot; aria-label=&quot;Snake case usage in TypeScript permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let’s look at the same TypeScript example and amend it ever-so-slightly to demonstrate when we may utilize the snake case naming convention.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; UserProps &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;   
  firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
  lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Serializable&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
	&lt;span class=&quot;token function&quot;&gt;toJSON&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Serializable&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MAX_USERS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Screaming snake case &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;                                         &lt;span class=&quot;token comment&quot;&gt;// to depict a constant&lt;/span&gt;&lt;/span&gt;	
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toJSON&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Variables are camel case&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userOne &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Khalil&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Stemmler&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userTwo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Nick&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Cave&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, snake case isn&apos;t a prevalent naming convention in C-styled languages like TypeScript. We only tend to use it when we&apos;re declaring constants.&lt;/p&gt;
&lt;h3 id=&quot;Snake-case-usage-in-Python&quot; style=&quot;position:relative;&quot;&gt;Snake case usage in Python&lt;a href=&quot;#Snake-case-usage-in-Python&quot; aria-label=&quot;Snake case usage in Python permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In Python, however, the snake case naming convention is much more common. Taking the same TypeScript example translated to Python, look at the widespread usage of snake case.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; json

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  props &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;first_name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Properties of dictionary objects&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;last_name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  MAX_USERS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Screaming snake case on constants&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;# Used on method parameters&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; first_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; last_name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;  
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;first_name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; first_name
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;last_name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; last_name
  
  &lt;span class=&quot;token comment&quot;&gt;# Usage on method names&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;to_JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; json&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dumps&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# We even use snake case to for naming variables&lt;/span&gt;
user_one &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Khalil&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Stemmler&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
user_two &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Nick&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Cave&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Pascal-case&quot; style=&quot;position:relative;&quot;&gt;Pascal case&lt;a href=&quot;#Pascal-case&quot; aria-label=&quot;Pascal case permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/camel-snake-pascal-case/pascal-case.png&quot; alt=&quot;pascal-case.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Pascal case follows the same camel case naming convention rules — all but one: we capitalize the first letter (e.g., &lt;em&gt;SomeVariable&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;In object-oriented languages like Java and TypeScript, we use pascal case to denote classes, namespaces, and abstractions like interfaces.&lt;/p&gt;
&lt;p&gt;In scripting languages like Python, you&apos;ll rarely find camel or pascal case code except when defining a class&apos;s name.&lt;/p&gt;
&lt;h3 id=&quot;Pascal-case-examples&quot; style=&quot;position:relative;&quot;&gt;Pascal case examples&lt;a href=&quot;#Pascal-case-examples&quot; aria-label=&quot;Pascal case examples permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;SomeVariable&lt;/li&gt;
&lt;li&gt;EventDispatcher&lt;/li&gt;
&lt;li&gt;EventsRepo&lt;/li&gt;
&lt;li&gt;SlackService&lt;/li&gt;
&lt;li&gt;ParentComment&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Pascal-case-usage-in-TypeScript&quot; style=&quot;position:relative;&quot;&gt;Pascal case usage in TypeScript&lt;a href=&quot;#Pascal-case-usage-in-TypeScript&quot; aria-label=&quot;Pascal case usage in TypeScript permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Continuing with the same example, let’s look at where pascal case is used in TypeScript code.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; UserProps &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// Types are also abstractions&lt;/span&gt;
  firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
  lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Serializable&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;// Interfaces use pascal case&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;toJSON&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Serializable&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// Class names use pascal case&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MAX_USERS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                                         
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toJSON&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userOne &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Khalil&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Stemmler&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userTwo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Nick&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Cave&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Comparison-of-naming-conventions-in-other-programming-languages&quot; style=&quot;position:relative;&quot;&gt;Comparison of naming conventions in other programming languages&lt;a href=&quot;#Comparison-of-naming-conventions-in-other-programming-languages&quot; aria-label=&quot;Comparison of naming conventions in other programming languages permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here’s a table that depicts all of the typical naming conventions for the languages: Python, C#, TypeScript, and Java.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Python&lt;/th&gt;
&lt;th&gt;C#&lt;/th&gt;
&lt;th&gt;TypeScript&lt;/th&gt;
&lt;th&gt;Java&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;functions &amp;#x26; methods&lt;/td&gt;
&lt;td&gt;snake_case()&lt;/td&gt;
&lt;td&gt;PascalCase()&lt;/td&gt;
&lt;td&gt;camelCase()&lt;/td&gt;
&lt;td&gt;camelCase()&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;classes&lt;/td&gt;
&lt;td&gt;PascalCase&lt;/td&gt;
&lt;td&gt;PascalCase&lt;/td&gt;
&lt;td&gt;PascalCase&lt;/td&gt;
&lt;td&gt;PascalCase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;interfaces&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;PascalCase&lt;/td&gt;
&lt;td&gt;PascalCase&lt;/td&gt;
&lt;td&gt;PascalCase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;namespaces&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;PascalCase&lt;/td&gt;
&lt;td&gt;PascalCase&lt;/td&gt;
&lt;td&gt;PascalCase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;constants&lt;/td&gt;
&lt;td&gt;snake_case&lt;/td&gt;
&lt;td&gt;SCREAMING&lt;em&gt;SNAKE\&lt;/em&gt;CASE&lt;/td&gt;
&lt;td&gt;SCREAMING_SNAKE_CASE&lt;/td&gt;
&lt;td&gt;SCREAMING_SNAKE_CASE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In summary,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Coding conventions are patterns, techniques, styles, and approaches to improve the maintainability of your code, and naming conventions are one of such techniques.&lt;/li&gt;
&lt;li&gt;Naming conventions improve maintainability by using consistency to optimize for discoverability and understanding.&lt;/li&gt;
&lt;li&gt;Naming conventions depend on the language. Each language has its own naming conventions that specify the use of programming tokens.&lt;/li&gt;
&lt;li&gt;Camel case (ex: camelCase) is usually for variables, properties, attributes, methods, and functions.&lt;/li&gt;
&lt;li&gt;Snake case (ex: snake_case) is commonly used in scripting languages like Python and as a constant in other C-styled languages.&lt;/li&gt;
&lt;li&gt;Pascal case (ex: PascalCase) is mainly reserved for class names, interfaces, and namespaces.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Whats-next&quot; style=&quot;position:relative;&quot;&gt;What’s next?&lt;a href=&quot;#Whats-next&quot; aria-label=&quot;Whats next permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you&apos;re &lt;a href=&quot;https://khalilstemmler.com/blogs/typescript/node-starter-project/&quot;&gt;setting up a new project&lt;/a&gt; or improving an existing one, I recommend you check out the series on &lt;a href=&quot;https://khalilstemmler.com/blogs/tooling/enforcing-husky-precommit-hooks/&quot;&gt;enforcing conventions with Husky&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Additionally, I&apos;m going to assume you&apos;re interested in learning about ways to improve the maintainability of your code. In that case, I recommend &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/introduction-to-tdd/&quot;&gt;learning TDD&lt;/a&gt;, &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/how-to-test-code-coupled-to-apis-or-databases/#Demonstration&quot;&gt;writing acceptance tests&lt;/a&gt;, and adopting a &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/feature-driven/&quot;&gt;feature-driven approach to software design&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to use Prettier with ESLint and TypeScript in VSCode]]></title><description><![CDATA[Intro In the previous article in this series, "How to use ESLint with TypeScript", we learned how add ESLint to our project and configure it…]]></description><link>https://khalilstemmler.com/blogs/tooling/prettier/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/tooling/prettier/</guid><pubDate>Sun, 19 Dec 2021 15:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;special-quote&quot;&gt;This post is a part of the &lt;b&gt;Clean Code Tooling&lt;/b&gt; series. &lt;br/&gt;You may want to read the previous post.&lt;br/&gt;&lt;a href=&quot;/blogs/typescript/eslint-for-typescript/&quot;&gt;1. How to use ESLint with TypeScript&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;Intro&quot; style=&quot;position:relative;&quot;&gt;Intro&lt;a href=&quot;#Intro&quot; aria-label=&quot;Intro permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the previous article in this series, &quot;&lt;a href=&quot;/blogs/typescript/eslint-for-typescript/&quot;&gt;How to use ESLint with TypeScript&lt;/a&gt;&quot;, we learned how add ESLint to our project and configure it to determine if our code was adhering to our project&apos;s coding conventions.&lt;/p&gt;
&lt;p&gt;This is great, but it can get pretty annoying having to re-run &lt;code class=&quot;language-text&quot;&gt;npm run lint&lt;/code&gt; everytime we want lint (and optionally fix) our code.&lt;/p&gt;
&lt;p&gt;Here&apos;s where &lt;a href=&quot;https://prettier.io/&quot;&gt;Prettier&lt;/a&gt;, particularly the &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode&quot;&gt;VS Code extension for Prettier&lt;/a&gt;, comes in.&lt;/p&gt;
&lt;h2 id=&quot;Understanding-Prettier&quot; style=&quot;position:relative;&quot;&gt;Understanding Prettier&lt;a href=&quot;#Understanding-Prettier&quot; aria-label=&quot;Understanding Prettier permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Prettier is an opinionated (yet fully configurable) code formatter. ESLint can &lt;em&gt;kind of&lt;/em&gt; format code too, but it&apos;s mostly intended to sniff out when we&apos;re not following the mandated coding conventions. &lt;/p&gt;
&lt;p&gt;Prettier can be configured to format your code (makes it look &lt;em&gt;prettier&lt;/em&gt; 😉) after you save a file or manually tell it to, and by default, it comes configured with a set of common code cleanliness rules.&lt;/p&gt;
&lt;p&gt;We get the most benefit out of Prettier when we combine it with ESLint though.&lt;/p&gt;
&lt;h2 id=&quot;Using-Prettier-with-ESLint&quot; style=&quot;position:relative;&quot;&gt;Using Prettier with ESLint&lt;a href=&quot;#Using-Prettier-with-ESLint&quot; aria-label=&quot;Using Prettier with ESLint permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Combining both ESLint &lt;em&gt;and&lt;/em&gt; Prettier, the responsibility division is this: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ESLint &lt;strong&gt;defines the code conventions&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Prettier &lt;strong&gt;performs the auto-formatting&lt;/strong&gt; based on the ESLint rules&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that&apos;s a bomb combo.&lt;/p&gt;
&lt;h2 id=&quot;Goals-for-this-blog-post&quot; style=&quot;position:relative;&quot;&gt;Goals for this blog post&lt;a href=&quot;#Goals-for-this-blog-post&quot; aria-label=&quot;Goals for this blog post permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At the end of this post, you should be able to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set up Prettier for a TypeScript or JavaScript project&lt;/li&gt;
&lt;li&gt;Decide on the formatting configuration that best suits your style&lt;/li&gt;
&lt;li&gt;Configure Prettier to work with ESLint&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Prerequisites&quot; style=&quot;position:relative;&quot;&gt;Prerequisites&lt;a href=&quot;#Prerequisites&quot; aria-label=&quot;Prerequisites permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A code editor installed (VS Code is the champ, don&apos;t @ me)&lt;/li&gt;
&lt;li&gt;An existing codebase (if you need to get setup, you can follow &quot;&lt;a href=&quot;/blogs/typescript/node-starter-project/&quot;&gt;How to Setup a TypeScript + Node.js Project&lt;/a&gt; first and then come back to this article)&lt;/li&gt;
&lt;li&gt;An understanding of ESLint and a working configuration (see &quot;&lt;a href=&quot;/blogs/typescript/eslint-for-typescript/&quot;&gt;How to use ESLint with TypeScript&lt;/a&gt;&quot; for an example)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Installing-Prettier&quot; style=&quot;position:relative;&quot;&gt;Installing Prettier&lt;a href=&quot;#Installing-Prettier&quot; aria-label=&quot;Installing Prettier permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First thing&apos;s first, we&apos;ll install Prettier as a dev dependency.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save-dev prettier&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Configuring-Prettier&quot; style=&quot;position:relative;&quot;&gt;Configuring Prettier&lt;a href=&quot;#Configuring-Prettier&quot; aria-label=&quot;Configuring Prettier permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As per the &lt;a href=&quot;https://prettier.io/docs/en/configuration.html&quot;&gt;docs&lt;/a&gt;, we can expose a JSON file called &lt;code class=&quot;language-text&quot;&gt;.prettierrc&lt;/code&gt; to put our configuration within.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; .prettierrc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A basic &lt;code class=&quot;language-text&quot;&gt;.prettierrc&lt;/code&gt; setting is the following:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;.prettierrc&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;semi&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;trailingComma&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;singleQuote&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;printWidth&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These settings specify the following rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;semi&lt;/code&gt; set to &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt; means that Prettier will add semicolons when necessary.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;trailingComma&lt;/code&gt; set to &lt;code class=&quot;language-text&quot;&gt;none&lt;/code&gt; means that Prettier will remove any trailing commas at the end of objects.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;singleQuote&lt;/code&gt; set to &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt; means that Prettier will &lt;em&gt;prefer&lt;/em&gt; single quotes instead of double quotes &lt;strong&gt;unless&lt;/strong&gt; the number of double-quotes outweighs the number of single-quotes. Read more &lt;a href=&quot;https://prettier.io/docs/en/options.html#quotes&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;printWidth&lt;/code&gt; set to &lt;code class=&quot;language-text&quot;&gt;80&lt;/code&gt; specifies that the printer will wrap any lines that exceed 80 characters.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can view the rest of the options &lt;a href=&quot;https://prettier.io/docs/en/options.html&quot;&gt;here&lt;/a&gt; and change them as you like! This is just my personal preference.&lt;/p&gt;
&lt;h2 id=&quot;Testing-Prettier-using-the-Prettier-CLI&quot; style=&quot;position:relative;&quot;&gt;Testing Prettier using the Prettier CLI&lt;a href=&quot;#Testing-Prettier-using-the-Prettier-CLI&quot; aria-label=&quot;Testing Prettier using the Prettier CLI permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So far, we&apos;ve locally configured Prettier, and we&apos;re in shape to test formatting some code.&lt;/p&gt;
&lt;p&gt;Since we&apos;re using the code from &lt;a href=&quot;https://github.com/stemmlerjs/simple-typescript-starter&quot;&gt;simple-typescript-starter&lt;/a&gt;, the only file we have is &lt;code class=&quot;language-text&quot;&gt;src/index.ts&lt;/code&gt;, and it looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Hello&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When we add a script to format all the code in the folder and execute it, the only change we should notice is an added semicolon.&lt;/p&gt;
&lt;p&gt;Add the following script to your &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;package.json&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ...
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;prettier-format&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;prettier --config .prettierrc &apos;src/**/*.ts&apos; --write&quot;&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then run it.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run prettier-format&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The console output shows that one file has been changed and that it took 186ms to execute.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run &lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; typescript-starter@1.0.0 &lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt; /simple-typescript-starter
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; prettier --config .prettierrc &lt;span class=&quot;token string&quot;&gt;&apos;src/**/*.ts&apos;&lt;/span&gt; --write

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;src/index.ts 186ms&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Looking at &lt;code class=&quot;language-text&quot;&gt;src/index.ts&lt;/code&gt;, you&apos;ll notice that the &lt;code class=&quot;language-text&quot;&gt;console.log&lt;/code&gt; was, in fact, appended with a semicolon.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Hello world!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is a neat way to use Prettier, but it&apos;s not the best, in my opinion. Here&apos;s what I prefer.&lt;/p&gt;
&lt;h2 id=&quot;Using-Prettier&quot; style=&quot;position:relative;&quot;&gt;Using Prettier&lt;a href=&quot;#Using-Prettier&quot; aria-label=&quot;Using Prettier permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the most common ways that people use Prettier is to install the &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode&quot;&gt;VS Code extension&lt;/a&gt; that adds it to your editor.&lt;/p&gt;
&lt;p&gt;It enables you to, on &lt;em&gt;save&lt;/em&gt;, format your code. This is good because the feedback loop is incredibly short, and it turns formatting into something that you don&apos;t have to occupy any brain cycles thinking about.&lt;/p&gt;
&lt;h3 id=&quot;Formatting-using-VSCode-on-save-recommended&quot; style=&quot;position:relative;&quot;&gt;Formatting using VSCode on save (recommended)&lt;a href=&quot;#Formatting-using-VSCode-on-save-recommended&quot; aria-label=&quot;Formatting using VSCode on save recommended permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Install the &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode&quot;&gt;Prettier VS Code extension&lt;/a&gt; here. &lt;/p&gt;
&lt;p&gt;To set the defaults, press &lt;code class=&quot;language-text&quot;&gt;CMD + SHIFT + P&lt;/code&gt; (on MacOS) or &lt;code class=&quot;language-text&quot;&gt;CTRL + Shift + P&lt;/code&gt; (on Windows), then type in &lt;code class=&quot;language-text&quot;&gt;preferences open settings&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You want to select the JSON option so that we can manually edit the preferences via a JSON file.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tooling/prettier/preferences-open-settings.png&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Options for typing in &quot;preferences open settings&quot;. You want to select the JSON option.&lt;/p&gt;
&lt;p&gt;In the JSON file, if it&apos;s not already added, add the following lines to the root of the object.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Default (format when you paste)&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;editor.formatOnPaste&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Default (format when you save)&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;editor.formatOnSave&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These settings will format your code both when you &lt;em&gt;paste&lt;/em&gt; new code and when you &lt;em&gt;save&lt;/em&gt; code for any file extension that Prettier understands. If the root of the project that the file lives in has a &lt;code class=&quot;language-text&quot;&gt;.prettierrc&lt;/code&gt;, it will use the settings that live in that file to format your code.&lt;/p&gt;
&lt;p&gt;Let&apos;s say you&apos;re working with multiple languages and automatically formatting code in another language is a no go for you. You can also override the default settings by specifying the language as shown below.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;[typescript]&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;editor.formatOnPaste&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;editor.formatOnSave&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;editor.formatOnPaste&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;editor.formatOnSave&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using the above config, Prettier will not format TypeScript code on &lt;em&gt;paste&lt;/em&gt; or &lt;em&gt;save&lt;/em&gt; but it &lt;strong&gt;will&lt;/strong&gt; format code on &lt;em&gt;paste&lt;/em&gt; or &lt;em&gt;save&lt;/em&gt; for any other language that it understands.&lt;/p&gt;
&lt;h3 id=&quot;Formatting-before-a-commit-recommended&quot; style=&quot;position:relative;&quot;&gt;Formatting before a commit (recommended)&lt;a href=&quot;#Formatting-before-a-commit-recommended&quot; aria-label=&quot;Formatting before a commit recommended permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When working with other developers as a team, it can be challenging to keep the formatting of the code clean constantly. Not everyone will want to use the Prettier VS Code extension. Not everyone will want to use &lt;em&gt;VS Code&lt;/em&gt;! &lt;/p&gt;
&lt;p&gt;How do we ensure that any code that gets commited and pushed to source control is properly formatted first?&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;Read the next post, &quot;&lt;a href=&quot;/blogs/tooling/enforcing-husky-precommit-hooks/&quot;&gt;Enforcing Coding Conventions with Husky Pre-commit Hooks&lt;/a&gt;&quot;.&lt;/p&gt;
&lt;h3 id=&quot;Formatting-using-an-filesystem-watcher&quot; style=&quot;position:relative;&quot;&gt;Formatting using an filesystem watcher&lt;a href=&quot;#Formatting-using-an-filesystem-watcher&quot; aria-label=&quot;Formatting using an filesystem watcher permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you &lt;em&gt;really&lt;/em&gt; don&apos;t like VS Code or there are too many people on your team not using it, there&apos;s another option to tighten the feedback loop of formatting code as you&apos;re writing it.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://prettier.io/docs/en/watching-files.html&quot;&gt;Prettier docsc&lt;/a&gt; suggest using a package called &lt;code class=&quot;language-text&quot;&gt;onchange&lt;/code&gt; in order to watch the filesystem for when changes are made to your source code, then run the Prettier CLI tool against any changed files.&lt;/p&gt;
&lt;p&gt;Here&apos;s how that works.&lt;/p&gt;
&lt;p&gt;Install &lt;code class=&quot;language-text&quot;&gt;onchange&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save-dev onchange&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, add this script to your &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;, making sure to change the &lt;em&gt;watched directory&lt;/em&gt; if you keep your source code in a location different the &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; folder.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;package.json&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;prettier-watch&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;onchange &apos;src/**/*.ts&apos; -- prettier --write {{changed}}&quot;&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Opening a new console, running &lt;code class=&quot;language-text&quot;&gt;prettier-watch&lt;/code&gt;, and editing code within the &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; folder will give us the same observable outcome as if we set Prettier up with VS Code or not.&lt;/p&gt;
&lt;h3 id=&quot;Manually-formatting-a-single-file&quot; style=&quot;position:relative;&quot;&gt;Manually formatting a single file&lt;a href=&quot;#Manually-formatting-a-single-file&quot; aria-label=&quot;Manually formatting a single file permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;On MacOS, if I&apos;ve installed the VS Code extension, I can format the current file by typing &lt;code class=&quot;language-text&quot;&gt;SHIFT + OPTION + F&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;This might be different for you. You can see what the command is by typing &lt;code class=&quot;language-text&quot;&gt;COMMAND + SHIFT + P&lt;/code&gt; and entering &quot;format&quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tooling/prettier/manual-format.png&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;The command to format the current file in VS Code is shown here for me.&lt;/p&gt;
&lt;h2 id=&quot;Configuring-Prettier-to-work-with-ESLint&quot; style=&quot;position:relative;&quot;&gt;Configuring Prettier to work with ESLint&lt;a href=&quot;#Configuring-Prettier-to-work-with-ESLint&quot; aria-label=&quot;Configuring Prettier to work with ESLint permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&apos;s where the real magic happens.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;As a reminder, you&apos;ll want to have completed the previous &lt;a href=&quot;/blogs/typescript/eslint-for-typescript/&quot;&gt;ESLint tutorial&lt;/a&gt; first.&lt;/p&gt;
&lt;p&gt;With ESLint and Prettier already installed, install these two packages as well. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save-dev eslint-config-prettier eslint-plugin-prettier&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;eslint-config-prettier&lt;/code&gt;: Turns off all ESLint rules that have the potential to interfere with Prettier rules.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;eslint-plugin-prettier&lt;/code&gt;: Turns Prettier rules into ESLint rules.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lastly, we need to make an adjustment to the &lt;code class=&quot;language-text&quot;&gt;.eslintrc&lt;/code&gt;. &lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;.eslintrc&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;parser&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint/parser&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;plugins&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;prettier&quot;&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;extends&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;eslint:recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;plugin:@typescript-eslint/eslint-recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;plugin:@typescript-eslint/recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;prettier&quot;&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;rules&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;no-console&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;       &lt;span class=&quot;token comment&quot;&gt;// Means warning&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;prettier/prettier&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Means error&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you&apos;re not interested in using the recommended plugins, the most basic &lt;code class=&quot;language-text&quot;&gt;.eslintrc&lt;/code&gt; with Prettier enabled looks like this:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;.eslintrc&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;extends&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;prettier&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;plugins&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;prettier&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;rules&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;prettier/prettier&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Means error&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Running &lt;code class=&quot;language-text&quot;&gt;npm run lint&lt;/code&gt; (from the previous article) lints the files and tells us all of the unformatted lines in addition to any code convention violations we&apos;ve protected against through ESLint rules.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;typescript-starter@1.0.0 lint /simple-typescript-starter
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; eslint &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; --ext .ts

simple-typescript-starter/src/index.ts
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;:1  error    Replace &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;⏎console.log&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Hello·world!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;⏎&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt; with &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;console.log&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Hello·world!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt;  prettier/prettier&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;:1  warning  Unexpected console statement                                                 no-console

✖ &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; problems &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; error, &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; warning&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; error and &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; warnings potentially fixable with the &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;--fix&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt; option.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&apos;s it! Run &lt;code class=&quot;language-text&quot;&gt;npm run prettier-format&lt;/code&gt; to format everything.&lt;/p&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p class=&quot;special-quote&quot;&gt;You can find the code for this post &lt;a href=&quot;https://github.com/stemmlerjs/simple-typescript-starter&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We&apos;re pretty lucky that tooling has advanced to the point where enforcing coding conventions and formatting code isn&apos;t something we have to personally concern ourselves with anymore.&lt;/p&gt;
&lt;p&gt;Even if you&apos;re not using VS Code, you should be able to add some basic formatting to your code using the steps outlined in this post.&lt;/p&gt;
&lt;p&gt;After that, the next step is to enforce your conventions and formatting within your team by using a tool like &lt;a href=&quot;https://github.com/typicode/husky&quot;&gt;Husky&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Read the final post in this series titled &quot;&lt;a href=&quot;/blogs/tooling/enforcing-husky-precommit-hooks/&quot;&gt;Enforcing Coding Conventions with Husky Pre-commit Hooks&lt;/a&gt;&quot;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to Test Code Coupled to APIs or Databases]]></title><description><![CDATA[In our humble introduction to Test-Driven Development, we learned the basics of TDD. You now know that you should start with a failing test…]]></description><link>https://khalilstemmler.com/articles/test-driven-development/how-to-test-code-coupled-to-apis-or-databases/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/test-driven-development/how-to-test-code-coupled-to-apis-or-databases/</guid><pubDate>Wed, 17 Nov 2021 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;In our humble &lt;a href=&quot;/articles/test-driven-development/introduction-to-tdd/&quot;&gt;introduction to Test-Driven Development&lt;/a&gt;, we learned the basics of TDD. You now know that you should start with a failing test, write the mininum amount of code to make it pass, and refactor it to make it cleaner. Red-green-refactor. &lt;/p&gt;
&lt;p&gt;Straightforward, right? Though it may take a while to internalize and start working this way, the physical aspect - the mechanics of it - are pretty easy to grasp. That&apos;s the good news.&lt;/p&gt;
&lt;p&gt;What&apos;s &lt;em&gt;not&lt;/em&gt; good news is that when you get out there into the real world, you&apos;re going to encounter situations where you need to test code that relies on a variety of &lt;strong&gt;infrastructural dependencies&lt;/strong&gt;: external APIs, services, databases, caches, webhooks, and so on.&lt;/p&gt;
&lt;p&gt;It is incredibly common for developers new to TDD to give up their test-driven journey at this point. When I first started with TDD years ago, it just didn&apos;t seem practical. I was only able to figure out how to TDD my way though simple things like simple functions or pure React components. &lt;/p&gt;
&lt;p&gt;The question then, is this: how do we test code that relies on &lt;em&gt;infrastructural&lt;/em&gt; concerns? Do we spin up a database, tear it down, and seed it everytime we want to write a unit test? Do we spend &lt;em&gt;real money&lt;/em&gt; everytime we want to test code that relies on a paid external API? (Hint: the answer is no, you don&apos;t &lt;em&gt;have&lt;/em&gt; to).&lt;/p&gt;
&lt;p&gt;In this post, we&apos;ll discuss how to test code that relies on infrastructure. And we&apos;ll do so by &lt;em&gt;first&lt;/em&gt; &lt;strong&gt;separating core code from infrastructure code&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Watch-on-YouTube&quot; style=&quot;position:relative;&quot;&gt;Watch on YouTube&lt;a href=&quot;#Watch-on-YouTube&quot; aria-label=&quot;Watch on YouTube permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;428px&quot; src=&quot;https://www.youtube.com/embed/ajfZqzeHp1E&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Please excuse the first few moments of bouncy video - I learned I can&apos;t rest my arm on my desk when recording video :)&lt;/b&gt; I&apos;m starting up &lt;a href=&quot;https://www.youtube.com/channel/UC-Lpxe2OBCsUXbMSS1zUu_g&quot;&gt;my YouTube channel&lt;/a&gt;! If you prefer this way of teaching, please like and subscribe ❤️.&lt;/p&gt;
&lt;h2 id=&quot;Core-code-and-infrastructure-code&quot; style=&quot;position:relative;&quot;&gt;Core code and infrastructure code&lt;a href=&quot;#Core-code-and-infrastructure-code&quot; aria-label=&quot;Core code and infrastructure code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What do I mean by &lt;em&gt;core code&lt;/em&gt; and &lt;em&gt;infrastructure code&lt;/em&gt;? And why is it important to keep them separate?&lt;/p&gt;
&lt;h3 id=&quot;Core-code&quot; style=&quot;position:relative;&quot;&gt;Core code&lt;a href=&quot;#Core-code&quot; aria-label=&quot;Core code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Core code is the heart of your application. This is your family jewels. It&apos;s what makes your app special.&lt;/p&gt;
&lt;p&gt;This code is also the code that represents the &lt;a href=&quot;/articles/software-design-architecture/feature-driven/#Essential-complexity&quot;&gt;essential complexity&lt;/a&gt;. It encapsulates the real-world complexity of the domain and the application.&lt;/p&gt;
&lt;p&gt;Consider a &lt;code class=&quot;language-text&quot;&gt;createUser&lt;/code&gt; &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use case&lt;/a&gt;. You need to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ol&gt;
&lt;li&gt;Check that that the user&apos;s details like their email and password are valid&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Check that the account wasn&apos;t already created, and &lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Confirm that the user&apos;s handle wasn&apos;t already taken&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because these rules represent the nature of the application and what makes the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use case&lt;/a&gt; succeed or fail, we call this &lt;a href=&quot;/articles/software-design-architecture/organizing-app-logic/#3-Application-Logic--Use-Cases&quot;&gt;application logic&lt;/a&gt;. Application logic usually depends on infrastructure, so depending on the way we write it, it &lt;em&gt;may&lt;/em&gt; or &lt;em&gt;may not&lt;/em&gt; be completely pure and decoupled from infrastructure.&lt;/p&gt;
&lt;p&gt;On the other hand, if we think a layer deeper, we get to &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/organizing-app-logic/#Clean-architecture-expanded&quot;&gt;domain logic&lt;/a&gt;. Domain logic is moreso about the data and behavior of the core business objects (think &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/entities/&quot;&gt;entities&lt;/a&gt; or &lt;code class=&quot;language-text&quot;&gt;Email&lt;/code&gt; &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-value-object/&quot;&gt;value objects&lt;/a&gt;). Because of this, we could benefit by thinking back to &lt;a href=&quot;/blogs/philosophy/existential-state-machines/#State-machines&quot;&gt;state machines&lt;/a&gt; and drawing out legal behavior. &lt;/p&gt;
&lt;p&gt;For example, let&apos;s consider a washing machine. The &lt;em&gt;state machine&lt;/em&gt; for a washing machine would illustrate the fact that you can go from &lt;code class=&quot;language-text&quot;&gt;OFF&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;ON&lt;/code&gt; and then &lt;code class=&quot;language-text&quot;&gt;WASH&lt;/code&gt;, but it would restrict you going from &lt;code class=&quot;language-text&quot;&gt;OFF&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;WASH&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;ON&lt;/code&gt;. That&apos;d put the washing machine into an &lt;a href=&quot;/articles/typescript-domain-driven-design/make-illegal-states-unrepresentable/&quot;&gt;illegal state&lt;/a&gt;. Domain logic is about enforcing these rules - typically validation and object behavior.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://khalilstemmler.com/img/blog/philosophy/existential-state-machines/washing-machine-state-machine.svg&quot; alt=&quot;Washing machine&quot;&gt;&lt;/p&gt;
&lt;p&gt;Domain logic is normally pure. It normally contains zero dependencies to &lt;em&gt;infrastructure&lt;/em&gt; and it is written by you. This makes it very easy to unit test. &lt;/p&gt;
&lt;p&gt;All of this stuff needs to get tested. As a test-driven developer, your goal is to turn the essential complexity that is your application and domain logic into &lt;em&gt;tested code&lt;/em&gt; - using the simplest, most flexible and maintainable way you know how. &lt;/p&gt;
&lt;h3 id=&quot;Infrastructure-code&quot; style=&quot;position:relative;&quot;&gt;Infrastructure code&lt;a href=&quot;#Infrastructure-code&quot; aria-label=&quot;Infrastructure code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the real world, the way to realize a web application is to integrate it with infrastructure. Application and domain logic can&apos;t do much if we can&apos;t host it somewhere in the cloud, if it doesn&apos;t maintain state somehow, or if we can&apos;t make requests to the backend API. &lt;/p&gt;
&lt;p&gt;On the backend, infrastructure code is denoted by concerns like your database, your cache, your local file system, or your REST or GraphQL web server. On the front-end, this is your view-layer library, your GraphQL or REST client, and your browser APIs.&lt;/p&gt;
&lt;p&gt;All of these concerns are things that we don&apos;t own. We either download them, connect to them over the network, or they exist as a part of the platform upon which our code executes. They are &lt;em&gt;infrastructural&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Unlike core code, we don&apos;t &lt;em&gt;unit test&lt;/em&gt; it &lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. Instead, we want to test the way that it &lt;em&gt;integrates&lt;/em&gt; — that&apos;s a key word: integrates. &lt;strong&gt;We want to test how it integrates with our code core&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Therefore, we write integration tests.&lt;/p&gt;
&lt;p&gt;For example, one particular type of integration test is called a &lt;em&gt;Contract Test&lt;/em&gt;. This ensures that - for example, our database adapter can save and retrieve objects in the way we expect it to.&lt;/p&gt;
&lt;p&gt;Therefore, we need to write different types of tests for different aspects of our application. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Integration tests for testing integrations&lt;/li&gt;
&lt;li&gt;Unit tests for testing the core application functionality — the most valuable aspects of our software&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What&apos;s stopping us from getting to the point where we can do this?&lt;/p&gt;
&lt;h2 id=&quot;The-problem-coupled-core-and-infrastructure-code&quot; style=&quot;position:relative;&quot;&gt;The problem: coupled core and infrastructure code&lt;a href=&quot;#The-problem-coupled-core-and-infrastructure-code&quot; aria-label=&quot;The problem coupled core and infrastructure code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The problem is that this isn&apos;t really possible when your core code and your infrastructure code is mixed. Actually, the better word to use is &lt;a href=&quot;https://khalilstemmler.com/wiki/coupling-cohesion-connascence/#Coupling&quot;&gt;coupled&lt;/a&gt; to each other.&lt;/p&gt;
&lt;p&gt;If your core code and your infrastructure code is coupled, we can&apos;t cleanly isolate parts of our code cleanly in order to write these specific types of tests.&lt;/p&gt;
&lt;p&gt;What we end up doing instead is coupling way too much core code in RESTful API controllers or GraphQL resolvers and suddenly, the only way to test the &lt;em&gt;application core&lt;/em&gt; (the &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/feature-driven/&quot;&gt;features&lt;/a&gt;, yes - the heart of our software) is to bring a database and a web server along for the ride. This makes things very slow and it makes tests harder to setup and teardown.&lt;/p&gt;
&lt;h2 id=&quot;Example-Coupled-feature&quot; style=&quot;position:relative;&quot;&gt;Example: Coupled feature&lt;a href=&quot;#Example-Coupled-feature&quot; aria-label=&quot;Example Coupled feature permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&apos;s an example of a feature with coupled core and infrastructure code.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;You can view the before and after code &lt;a href=&quot;https://github.com/stemmlerjs/how-to-test-code-reliant-on-apis&quot; target=&quot;_blank&quot;&gt;here on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// modules/users/useCases/createUser/index.ts&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; express &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;express&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; User &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../domain/user&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; firebaseUserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../repos&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UsersService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../services/usersService&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Check to see if firstname, lastname, password, email is in the request&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isFirstNamePresent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isLastNamePresent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isEmailPresent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isPasswordPresent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// If not, end the request&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isFirstNamePresent &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isEmailPresent &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isLastNamePresent &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isPasswordPresent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Either &apos;firstName&apos;, &apos;lastName&apos;, &apos;email&apos; or &apos;password not present&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Check to see if already registered&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; existingUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; firebaseUserRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findByEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
    &lt;span class=&quot;token comment&quot;&gt;// If already registered, return AlreadyRegisteredError&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;existingUser&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;409&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;AlreadyRegisteredError&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;User already registered&apos;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; errorMessage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Validation logic&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UsersService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;validateFirstName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      errorMessage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Invalid firstName&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UsersService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;validateLastName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      errorMessage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Invalid lastName&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UsersService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;validateEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      errorMessage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Invalid email&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UsersService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;validatePassword&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      errorMessage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Invalid password&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// If invalid props, return InvalidUserDetailsError&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;errorMessage&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;InvalidUserDetailsError&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; errorMessage
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Create user&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      password&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;password
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Save user to database&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; firebaseUserRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Log this to monitoring or logging plugin but don&apos;t return&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// the backend error to the client.&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Unexpected error occurred&apos;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;201&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;CreateUserSuccess&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Success&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What&apos;s wrong with this? Well, there&apos;s nothing really &lt;em&gt;wrong&lt;/em&gt; with this of course. The code works. However, the only way for us to test this would be to perform a &lt;em&gt;black-box test&lt;/em&gt;: an End-to-End test. Why? Because in order to set up this test, we need to bring an entire Express.js webserver with us, connections to a real firebase instance, and we can only validate the &lt;em&gt;application logic&lt;/em&gt; through response codes.&lt;/p&gt;
&lt;p&gt;While I believe E2E testing should be a part of your testing strategy, I don&apos;t think it should &lt;em&gt;be&lt;/em&gt; your testing strategy. &lt;/p&gt;
&lt;p&gt;Let&apos;s now discuss the path to fixing this.&lt;/p&gt;
&lt;h2 id=&quot;Architectural-patterns&quot; style=&quot;position:relative;&quot;&gt;Architectural patterns&lt;a href=&quot;#Architectural-patterns&quot; aria-label=&quot;Architectural patterns permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://wiki.solidbook.io/Part-VIII-Architecture-Essentials-1a37541c710145829b79f9d2814946fc&quot;&gt;Part VII - Architecture Essentials&lt;/a&gt; from solidbook.io, we learn about &lt;strong&gt;architectural styles&lt;/strong&gt; and &lt;strong&gt;architectural patterns&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Architectural styles are general overarching ways in which you can construct your application to help you solve a particular architectural challenge. The three main ones being &lt;em&gt;structural&lt;/em&gt;, &lt;em&gt;message-based&lt;/em&gt;, and &lt;em&gt;distributed&lt;/em&gt; architectures.&lt;/p&gt;
&lt;p&gt;It&apos;s kind of like how we have &lt;em&gt;design patterns&lt;/em&gt;. Where we typically think of design patterns as these things that help us solve challenges at the class level, &lt;strong&gt;architectural styles and their patterns help us solve problems at the architectural level&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Architectural challenge? What&apos;s the challenge we&apos;re facing here? &lt;/p&gt;
&lt;p&gt;The challenge 95% of us who are building non-trivial production applications are tasked with is not only how to encode these business rules within software effectively, but to do so in a way that we can verify that they work, and that we can safely change those rules later on down the road.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In other words, the challenge is that we have &lt;strong&gt;strict testing requirements&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which architectural pattern is specifically meant to help us solve the strict testing requirement problem? Ah yes, the layered architecture.&lt;/p&gt;
&lt;h2 id=&quot;A-layered-architecture&quot; style=&quot;position:relative;&quot;&gt;A layered architecture&lt;a href=&quot;#A-layered-architecture&quot; aria-label=&quot;A layered architecture permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The solution to our testing problem is a &lt;em&gt;structural&lt;/em&gt; architectural style called the layered architecture.&lt;/p&gt;
&lt;p&gt;If you&apos;re a regular reader of this blog, you&apos;re likely already familiar with it, perhaps by the name of a hexagonal architectural, the onion architecture, or the famous clean architecture.&lt;/p&gt;
&lt;p&gt;For those uninitiated, the main idea is that you separate the concerns of your application into layers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A layer for domain logic&lt;/li&gt;
&lt;li&gt;One for application&lt;/li&gt;
&lt;li&gt;One for infrastructure&lt;/li&gt;
&lt;li&gt;And an adapter layer which merely describes &lt;em&gt;abstractions&lt;/em&gt; that make it possible for your infrastructure to hook into your application layer code using &lt;a href=&quot;/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;dependency injection&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/app-logic-layers.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;Core code corresponds to the domain, application, and adapter&lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; layers while infrastructure corresponds to the infrastructure layer.&lt;/p&gt;
&lt;h3 id=&quot;Benefit--testing-options&quot; style=&quot;position:relative;&quot;&gt;Benefit — testing options&lt;a href=&quot;#Benefit--testing-options&quot; aria-label=&quot;Benefit  testing options permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The primary benefit of this type of separation is that we &lt;em&gt;give ourselves&lt;/em&gt; a lot more &lt;a href=&quot;https://wiki.solidbook.io/25-Testing-Strategies-0794bd15f6324a6d90558c3819cf0630/&quot;&gt;testing options&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Before, if we wanted to write our &lt;a href=&quot;https://wiki.solidbook.io/22-Acceptance-Tests-7bf96fa035694e329455c11c740ab9a7&quot;&gt;acceptance tests&lt;/a&gt;, we&apos;d have to write them in a sort of E2E-test style, bringing all of our databases, services, and real-world APIs along for the ride, maybe even playing with &lt;em&gt;real money&lt;/em&gt; or something.&lt;/p&gt;
&lt;p&gt;Instead, if we want to write our acceptance tests as &lt;em&gt;unit tests&lt;/em&gt;, we have the option for that now.&lt;/p&gt;
&lt;p&gt;For a &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/use-case-tests-mocking/&quot;&gt;use case test&lt;/a&gt;, we can mock and stub out dependencies to infrastructure and just focus on testing the application core — make sure that it fails when it should, that it attempts to save to the database, that it attempts to make a call to an external API, or delete something when it &lt;em&gt;should&lt;/em&gt; — but without actually &lt;em&gt;really&lt;/em&gt; making that happen.&lt;/p&gt;
&lt;p&gt;Then if we want to test that our infrastructure &lt;em&gt;does work&lt;/em&gt;, we can test that separately in integration tests. This is just a part of a larger testing strategy. But alas — now we have options.&lt;/p&gt;
&lt;p&gt;Let me show you how I&apos;d probably rewrite and acceptance test this feature using the layered architecture pattern.&lt;/p&gt;
&lt;h3 id=&quot;Demonstration&quot; style=&quot;position:relative;&quot;&gt;Demonstration&lt;a href=&quot;#Demonstration&quot; aria-label=&quot;Demonstration permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&apos;d start with the BDD-style Given-When-Then test.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;gherkin&quot;&gt;&lt;pre class=&quot;language-gherkin&quot;&gt;&lt;code class=&quot;language-gherkin&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# modules/users/useCases/createUser/createUser.feature&lt;/span&gt;
&lt;span class=&quot;token feature&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Feature:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Create user&lt;/span&gt;

&lt;/span&gt;&lt;span class=&quot;token scenario&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Scenario:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Creating a user&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token atrule&quot;&gt;Given&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; provide valid user details
  &lt;span class=&quot;token atrule&quot;&gt;When&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; attempt to create a user
  &lt;span class=&quot;token atrule&quot;&gt;Then&lt;/span&gt; the user should be saved successfully 

&lt;span class=&quot;token scenario&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Scenario:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Invalid password&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token atrule&quot;&gt;Given&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; provide an invalid password
  &lt;span class=&quot;token atrule&quot;&gt;When&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; attempt to create a user
  &lt;span class=&quot;token atrule&quot;&gt;Then&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; should get an invalid details error &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then I&apos;d write the test:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// modules/users/useCases/createUser/createUser.spec.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; defineFeature&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; loadFeature &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;jest-cucumber&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; path &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;path&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IUserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../repos/userRepo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CreateUser&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CreateUserResult &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./createUser&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserRepoSpy &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../testObjects/userRepoSpy&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; feature &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loadFeature&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./createUser.feature&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;defineFeature&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;feature&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; result&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CreateUserResult&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; password&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; createUser&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CreateUser&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; userRepoSpy&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserRepoSpy&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;beforeEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    createUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    userRepoSpy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Creating a user&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; given&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; when&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; then &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    
    &lt;span class=&quot;token function&quot;&gt;given&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;I provide valid user details&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Arrange&lt;/span&gt;
      email &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;khalil@khalilstemmler.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      password &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;hello&apos;&lt;/span&gt;
      firstName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;khalil&apos;&lt;/span&gt;
      lastName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;stemmler&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      userRepoSpy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserRepoSpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      createUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userRepoSpy&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;I attempt to create a user&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Act&lt;/span&gt;
      result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; createUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;the user should be saved successfully&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Assert&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;CreateUserSuccess&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userRepoSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getTimesSaveCalled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Invalid password&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; given&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; when&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; then &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;given&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;I provide an invalid password&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      email &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;khalil@khalilstemmler.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      password &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;
      firstName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;khalil&apos;&lt;/span&gt;
      lastName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;stemmler&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      userRepoSpy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserRepoSpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      createUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userRepoSpy&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;I attempt to create a user&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; createUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;I should get an invalid details error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Assert&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;InvalidUserDetailsError&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userRepoSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getTimesSaveCalled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then I&apos;d write the implementation of the &lt;em&gt;use case&lt;/em&gt; (worrying about the integration tests later):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// modules/users/useCases/createUser/createUser.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Result &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../../../shared/core/result&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UseCase &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../../../shared/core/useCase&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Email &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../domain/email&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; FirstName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../domain/firstName&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; LastName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../domain/lastName&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../domain/password&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; User &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../domain/user&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IUserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../repos/userRepo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; CreateUserInput &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  password&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
  lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; CreateUserSuccess &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;CreateUserSuccess&apos;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; AlreadyRegisteredError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;AlreadyRegisteredError&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; InvalidUserDetailsError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;InvalidUserDetailsError&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; UnexpectedError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;UnexpectedError&apos;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; CreateUserResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; CreateUserSuccess 
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; AlreadyRegisteredError 
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; InvalidUserDetailsError
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; UnexpectedError&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUser&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;CreateUserInput&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CreateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CreateUserInput&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;CreateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Check to see if already registered&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; existingUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findByEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
    &lt;span class=&quot;token comment&quot;&gt;// If already registered, return AlreadyRegisteredError&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;existingUser&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;AlreadyRegisteredError&apos;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Validation logic&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; emailOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; firstNameOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FirstName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; lastNameOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; LastName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; passwordOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Password&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; combinedResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;combine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; 
      emailOrError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstNameOrError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastNameOrError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; passwordOrError 
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;combinedResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;InvalidUserDetailsError&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; combinedResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;errorValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; userOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; emailOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      password&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; passwordOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Password&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; firstNameOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; FirstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; lastNameOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; LastName
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;InvalidUserDetailsError&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; userOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;errorValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Save user to database&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Log this to monitoring or logging plugin but don&apos;t return&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// the backend error to the client.&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;UnexpectedError&apos;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;CreateUserSuccess&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;There are many nuances in this improved version. Read about &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/use-case-tests-mocking/&quot; target=&quot;_blank&quot;&gt;Use case Tests&lt;/a&gt; or check out &lt;a href=&quot;https://www.youtube.com/embed/ajfZqzeHp1E&quot; target=&quot;_blank&quot;&gt;the YouTube video for this article&lt;/a&gt; for a more detailed breakdown.&lt;/p&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To recap, we learned that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The big problem with testing code that relies on databases, APIs, the file-system, or anything infrastructural is that we often &lt;em&gt;couple our core code&lt;/em&gt; — the actual application core, the essential complexity — to our &lt;em&gt;infrastructural code&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Architectural styles and patterns are solutions to common architectural problems. &lt;/li&gt;
&lt;li&gt;The reason the layered architecture is so helpful for testing is that that it allows us to use dependency inversion to separate core code from infrastructure code. This gives us testing options. We can then develop a testing strategy that works.&lt;/li&gt;
&lt;li&gt;One way to acceptance test your features is to use a [Use ], by using a Use Case test, which is able to test the application core without relying on infrastructure — and that&apos;s very handy because it enables us to exhaust all of the success and failure states without needing to bring slow database connections or network requests along for the ride.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;FAQ&quot; style=&quot;position:relative;&quot;&gt;FAQ&lt;a href=&quot;#FAQ&quot; aria-label=&quot;FAQ permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Question-Do-I-have-to-do-this&quot; style=&quot;position:relative;&quot;&gt;Question: Do I have to do this?&lt;a href=&quot;#Question-Do-I-have-to-do-this&quot; aria-label=&quot;Question Do I have to do this permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Do I &lt;em&gt;have&lt;/em&gt; to do this to test my backend code? Of course not. If you&apos;re building something super simple like a CRUD app, a proof of concept, or just exploring, I don&apos;t think you need to get to this level.&lt;/p&gt;
&lt;p&gt;You can always just merely black-box test your entire backend, meaning — from the API, you just send it HTTP requests and assume that things work properly if your database get saved with the appropriate records.&lt;/p&gt;
&lt;p&gt;This does, however, leave a lot of gaps in our testing capabilities.&lt;/p&gt;
&lt;p&gt;For example, how exactly would you be able to verify that a confirmation email was sent when it should have been? You can&apos;t exactly programmatically log into your Gmail account to find that out.&lt;/p&gt;
&lt;p&gt;I think you normally want a mixture of this black-box testing — testing from the outside, and some white-box testing, testing from the inside. Having both is a part of a healthy testing strategy on any software you intend on maintaining for an extended period of time.&lt;/p&gt;
&lt;h3 id=&quot;Question-Is-this-just-on-back-end-or-does-this-apply-to-front-end-too&quot; style=&quot;position:relative;&quot;&gt;Question: Is this just on back-end or does this apply to front-end too?&lt;a href=&quot;#Question-Is-this-just-on-back-end-or-does-this-apply-to-front-end-too&quot; aria-label=&quot;Question Is this just on back end or does this apply to front end too permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can also decouple the layers of your front-end code as well.&lt;/p&gt;
&lt;p&gt;I&apos;ve written a little bit of philosophy on &lt;a href=&quot;https://khalilstemmler.com/articles/client-side-architecture/introduction/&quot;&gt;how this would work in the front-end via Client-Side Architecture Basics&lt;/a&gt;, and while I sometimes use these techniques, it depends on the testing requirements.&lt;/p&gt;
&lt;p&gt;For example, if you&apos;re building what I call a &lt;em&gt;list/detail-view application&lt;/em&gt; where all you really have to do is fetch data and present it, then no - I don&apos;t think this is entirely necessary. Your front-end testing strategy could just be to perform E2E tests and that&apos;s it (though I&apos;d advise writing these tests in as BDD-acceptance-test-style as possible).&lt;/p&gt;
&lt;p&gt;However, if you&apos;re building something very complex, like a digitial audio workstation in your browser, and there&apos;s a lot of logic that cannot be tested by merely perceiving and clicking, then yes, you&apos;re going to want to enforce a more rigid set of architectural layers for unit testing application or domain logic as well.&lt;/p&gt;
&lt;p&gt;So ultimately, it depends on your testing requirements. How rigid are they? What&apos;s your testing strategy?&lt;/p&gt;
&lt;h3 id=&quot;Question-What-about-testing-React-components-How-do-you-test-them&quot; style=&quot;position:relative;&quot;&gt;Question: What about testing React components? How do you test them?&lt;a href=&quot;#Question-What-about-testing-React-components-How-do-you-test-them&quot; aria-label=&quot;Question What about testing React components How do you test them permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&apos;s apply the same philosophy.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Understand what it is that we&apos;d like to test&lt;/li&gt;
&lt;li&gt;Develop a testing strategy&lt;/li&gt;
&lt;li&gt;Separate core code from infrastructure code&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It depends on what you&apos;d like to do. If you&apos;d like to test your pure react components with unit tests, then yes — we&apos;ll want to enforce some level of separation, especially if it relies on infrastructure like Apollo Client or an HTTP-enabled service class or React hook that fetches data from a RESTful API.&lt;/p&gt;
&lt;p&gt;If you don&apos;t care so much about testing your React components, and you care more about testing the features of the application from a user level (very common for view/list-detail applications), this calls for E2E tests. And it doesn&apos;t call for a strict decoupling of core from infrastructure. Go right ahead and write your E2E tests on &lt;em&gt;top&lt;/em&gt; of your React code. Even better, &lt;em&gt;start&lt;/em&gt; by &lt;a href=&quot;https://wiki.solidbook.io/26-The-Walking-Skeleton-a8bec641f8544b0aa1645f7290e93579#use-page-objects-to-write-declarative-e2e-tests&quot;&gt;writing your E2E tests using the Page Object pattern&lt;/a&gt;, and then write the minimum required React code to make your E2E tests pass.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;People seem to have different opinions on what a unit test &lt;em&gt;is&lt;/em&gt; and &lt;em&gt;is not&lt;/em&gt;. I do not believe that testing a component which contains other components disqualifies my test from being a unit test. For example, if I wanted to test a pure React component, like &lt;code class=&quot;language-text&quot;&gt;Table&lt;/code&gt; and it was decomposed into smaller sub-components for purely cosmetic reasons like &lt;code class=&quot;language-text&quot;&gt;TableRow&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;TableColumn&lt;/code&gt;, I still believe testing &lt;code class=&quot;language-text&quot;&gt;Table&lt;/code&gt; is a valid unit test. Why? Because I believe unit tests are more about if we&apos;re testing core code or infrastructure code. If we test code that relies on databases, network requests, the filesystem, or &lt;strong&gt;even the system clock&lt;/strong&gt;, we are no longer testing units - we are testing integrations. Integrations between what? Between code &lt;em&gt;you wrote&lt;/em&gt; (core) and code &lt;em&gt;someone else wrote&lt;/em&gt; (infrastructure). This is the strategy we use for acceptance testing as &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/use-case-tests-mocking/&quot;&gt;use case tests&lt;/a&gt;.&lt;/p&gt;
&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Technically, you can say the adapter layer is a core layer because it doesn&apos;t contain any infrastructural concerns. It&apos;s completely comprised of abstractions. I like to think of it as a bridge between core and infrastructure.&lt;/p&gt;
&lt;a href=&quot;#fnref-2&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[No title]]></title><description><![CDATA[In a layered architecture there are often a number of mutable, shared, external, out-of-process infrastructural dependencies. We can break…]]></description><link>https://khalilstemmler.com/wiki/managed-vs-unmanaged-dependencies/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/managed-vs-unmanaged-dependencies/</guid><pubDate>Sun, 08 Aug 2021 04:05:26 GMT</pubDate><content:encoded>&lt;p&gt;In a &lt;a href=&quot;/articles/software-design-architecture/organizing-app-logic/&quot;&gt;layered architecture&lt;/a&gt; there are often a number of mutable, shared, external, out-of-process infrastructural dependencies. We can break these down even further into two categories: managed or unmanaged.&lt;/p&gt;
&lt;h2 id=&quot;Managed-dependencies&quot; style=&quot;position:relative;&quot;&gt;Managed dependencies&lt;a href=&quot;#Managed-dependencies&quot; aria-label=&quot;Managed dependencies permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;An external, mutable, out-of-process, shared dependency is considered managed when we:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;have full control over it because it is specific to our application AND &lt;/li&gt;
&lt;li&gt;interactions with it are hidden from the outside world AND &lt;/li&gt;
&lt;li&gt;if an external system wants to interact with it, that has to be done through your application&apos;s API&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Examples-of-managed-dependencies&quot; style=&quot;position:relative;&quot;&gt;Examples of managed dependencies&lt;a href=&quot;#Examples-of-managed-dependencies&quot; aria-label=&quot;Examples of managed dependencies permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Your application database&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;How-to-test-managed-dependencies&quot; style=&quot;position:relative;&quot;&gt;How to test managed dependencies&lt;a href=&quot;#How-to-test-managed-dependencies&quot; aria-label=&quot;How to test managed dependencies permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The best way to test a managed dependency like an application database is to write a &lt;em&gt;contract test&lt;/em&gt; (which is a form of an integration test). &lt;/p&gt;
&lt;p&gt;Since the interface for your repository object defines all of the things an implementatation must be able to do, your test exercises each of the methods in the interface, confirming that each works properly.&lt;/p&gt;
&lt;p&gt;There is absolutely no mocking in this type of test. It needs to be as real as possible. &lt;/p&gt;
&lt;h2 id=&quot;Unmanaged-dependencies&quot; style=&quot;position:relative;&quot;&gt;Unmanaged dependencies&lt;a href=&quot;#Unmanaged-dependencies&quot; aria-label=&quot;Unmanaged dependencies permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;An external, mutable, out-of-process, shared dependency is considered unmanaged when we:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;don&apos;t have full control over it because part of it is not fully owned by us OR&lt;/li&gt;
&lt;li&gt;it is also used by other applications and changing it could potentially break other applications&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Examples-of-unmanaged-dependencies&quot; style=&quot;position:relative;&quot;&gt;Examples of unmanaged dependencies&lt;a href=&quot;#Examples-of-unmanaged-dependencies&quot; aria-label=&quot;Examples of unmanaged dependencies permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A message bus (used by other applications in your enterprise)&lt;/li&gt;
&lt;li&gt;An email-sending adapter (because it &lt;em&gt;actually&lt;/em&gt; sends an email using an email service like Sendgrid or Mailchimp)&lt;/li&gt;
&lt;li&gt;A payments API like Stripe or PayPal&lt;/li&gt;
&lt;li&gt;Any other external API not owned by you or your team&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;How-to-test-unmanaged-dependencies&quot; style=&quot;position:relative;&quot;&gt;How to test unmanaged dependencies&lt;a href=&quot;#How-to-test-unmanaged-dependencies&quot; aria-label=&quot;How to test unmanaged dependencies permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In a layered architecture, there are two ways we can test unmanaged dependencies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;Use case&lt;/a&gt; &lt;a href=&quot;/articles/test-driven-development/use-case-tests-mocking/&quot;&gt;test&lt;/a&gt;: Test that our application will call the &lt;a href=&quot;https://khalilstemmler.com/articles/oop-design-principles/command-query-separation&quot;&gt;command-like&lt;/a&gt; operation at the correct time and with the correct arguments&lt;/li&gt;
&lt;li&gt;Integration test: Test that we can communicate with the external, unmanaged dependency&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, production usage of unmanaged dependencies might look like the following:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Publishing an event onto an event bus&lt;/span&gt;
bus&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;publishEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Sending an email&lt;/span&gt;
emailService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Charging a credit card&lt;/span&gt;
stripe&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createCharge&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;customer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Because both tests test different aspects of the application, it&apos;s often a good idea to write both use case tests &lt;em&gt;and&lt;/em&gt; integration tests.&lt;/p&gt;
&lt;h4 id=&quot;Use-case-testing-unmanaged-dependencies&quot; style=&quot;position:relative;&quot;&gt;Use case testing unmanaged dependencies&lt;a href=&quot;#Use-case-testing-unmanaged-dependencies&quot; aria-label=&quot;Use case testing unmanaged dependencies permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;In &lt;a href=&quot;/articles/test-driven-development/use-case-tests-mocking/&quot;&gt;use case tests&lt;/a&gt;, the way we verify that our application has called these dependencies at the right time and with the correct parameters, is to use a &lt;a href=&quot;/wiki/test-doubles/#Mocks&quot;&gt;mock&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Rule: As per the &lt;a href=&quot;https://khalilstemmler.com/articles/oop-design-principles/command-query-separation&quot;&gt;CQS principle&lt;/a&gt;, only use mocks to assert against &lt;em&gt;commands&lt;/em&gt; (outgoing interactions); never use mocks for &lt;em&gt;queries&lt;/em&gt; (use &lt;a href=&quot;/wiki/test-doubles/#Stubs&quot;&gt;stubs&lt;/a&gt; for that)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Consider we&apos;re writing a &lt;code class=&quot;language-text&quot;&gt;makeOffer&lt;/code&gt; &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use case&lt;/a&gt; in a vinyl-trading application. Using a use case test to ensure that it works properly, one &lt;strong&gt;observable outcome/state change&lt;/strong&gt; is to test that an email gets sent to the vinyl owner.&lt;/p&gt;
&lt;p&gt;Because we don&apos;t want to pass in a &lt;em&gt;real&lt;/em&gt; email-sending service that actually sends emails, we&apos;ll need a way to validate that the use case told the (unmanaged) dependency - the outgoing adapter - to send the email.&lt;/p&gt;
&lt;p&gt;We can do this with either a mock or a spy (the difference is that a spy is a &lt;em&gt;hand-coded version of a mock&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;We will use both a mock and a spy in the following example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// modules/notification/notificationService.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;INotificationService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;sendEmail&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// modules/trading/useCases/makeOffer/makeOffer.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MakeOffer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; vinylRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; tradesRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ITradesRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; notificationService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; INotificationService&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Implementation here&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// modules/notification/mocks/notificationsSpy.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INotificationService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./makeOffer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Here, we define an `INotificationService` which can be subtituted in.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// We keep track of the emails sent and write specific methods in order&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// to help us assert that we&apos;ll have called a command-like operation&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// (the outcome-related behavior) when we should have.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NotificationsSpy&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;INotificationService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; emailsSent&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailsSent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// This is the behavior related to the outcome. The command.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sendEmail&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailsSent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// This is a method we add to make it easier to assert &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// in our test.&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getEmailsSent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailsSent&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// modules/trading/useCases/makeOffer/makeOffer.spec.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ITradesRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MakeOffer &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./makeOffer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; NotificationsSpy &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./notificationSpy&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createMock &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ts-auto-mock&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;makeOffer&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Given a vinyl exists and is available for trade&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;When a trader wants to place an offer using money&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Then the offer should get created and an email should be sent to the vinyl owner&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Arrange &lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Stub: This is used to perform a query - no assertion on this&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; fakeVinylRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; createMock&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IVinylRepo&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;token comment&quot;&gt;// Mocks: These are used to validate commands (state changes)&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; mockTradesRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; createMock&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ITradesRepo&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; notificationsSpy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NotificationsSpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; makeOffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MakeOffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          fakeVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
          mockTradesRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          notificationsSpy
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Act &lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; makeOffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;123&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          tradeType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;money&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          amountInCents&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;35&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Assert &lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mockTradesRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;save&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;notificationsSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getEmailsSent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Some people will say &quot;use mocks for unmanaged dependencies (external APIs, etc). Don&apos;t use mocks for managed ones (application database)&quot;. This doesn&apos;t take into consideration cases when you&apos;re using your database as event storage and it also then says that it&apos;s illegal for you to confirm that you&apos;ve performed a &lt;code class=&quot;language-text&quot;&gt;save()&lt;/code&gt; operation at the end of a use case (which, according to the following test, is part of what we should be testing).&lt;/p&gt;
&lt;p&gt;I think a better rule is the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Rule: Use mocks for commands, use stubs for queries&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A Google search on this principle informs me that &lt;a href=&quot;https://blog.ploeh.dk/2013/10/23/mocks-for-commands-stubs-for-queries/&quot;&gt;Mark Seemann agrees&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also, because queries can be seen as implementation details:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Rule: Do not perform assertions on queries&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If we&apos;re unit testing a query (use case) and we want to ensure that it returns the correct data, we should only assert on the result.&lt;/p&gt;
&lt;h4 id=&quot;Integration-testing-unmanaged-dependencies&quot; style=&quot;position:relative;&quot;&gt;Integration testing unmanaged dependencies&lt;a href=&quot;#Integration-testing-unmanaged-dependencies&quot; aria-label=&quot;Integration testing unmanaged dependencies permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Since other types of tests cover the &lt;em&gt;contract&lt;/em&gt; and &lt;em&gt;behavior&lt;/em&gt;, all we care about is that our application can communicate with the dependency. For example, if we&apos;re using Stripe&apos;s payment API, we merely want to ensure that our application can connect to Stripe.&lt;/p&gt;
&lt;p&gt;This is substantially trickier. As Matthias Noback suggests in “Advanced Web Application Architecture”, you can either:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Write the test against the real service&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;special-green&quot;&gt; (Ideal) Write the test against a sandbox environment the third party offers&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Write the test against a fake server that you run&lt;/li&gt;
&lt;li&gt;Write the test against a fake or mock HTTP client offered by the client library that you use&lt;/li&gt;
&lt;li&gt;Write the test against a fake or mock of the HTTP client interface that you use&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;Further-reading&quot; style=&quot;position:relative;&quot;&gt;Further reading&lt;a href=&quot;#Further-reading&quot; aria-label=&quot;Further reading permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://enterprisecraftsmanship.com/posts/when-to-mock/&quot;&gt;https://enterprisecraftsmanship.com/posts/when-to-mock/&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[No title]]></title><description><![CDATA[Originating from the idea of a stunt double (like in action movies), there are two general categories of testing objects that we use in…]]></description><link>https://khalilstemmler.com/wiki/test-doubles/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/test-doubles/</guid><pubDate>Sun, 08 Aug 2021 04:05:26 GMT</pubDate><content:encoded>&lt;p&gt;Originating from the idea of a stunt double (like in action movies), there are two general categories of testing objects that we use in testing: mocks and stubs.&lt;/p&gt;
&lt;h2 id=&quot;Mocks&quot; style=&quot;position:relative;&quot;&gt;Mocks&lt;a href=&quot;#Mocks&quot; aria-label=&quot;Mocks permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mocks&lt;/strong&gt;: We use a mock to stand in and &lt;strong&gt;assert&lt;/strong&gt; against command-like operations (outgoing interactions or state changes against dependencies). We pass mocks in to the system under test (SUT) and later check during the &lt;em&gt;assert&lt;/em&gt; phase of a test that the correct calls to change the dependencies&apos; state were made. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spies&lt;/strong&gt;: These are exactly the same thing as traditional mocks except that we &lt;em&gt;hand-roll&lt;/em&gt; spies manually, whereas with traditional mocks, mocking libraries like &lt;a href=&quot;https://github.com/Typescript-TDD/ts-auto-mock&quot;&gt;ts-auto-mock&lt;/a&gt; help you create mocks in a single line or two (I highly recommend this package over basic mocking with Jest). You can see &lt;a href=&quot;/wiki/managed-vs-unmanaged-dependencies/#Use-case-testing-unmanaged-dependencies&quot;&gt;an example of a hand-rolled spy here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Stubs&quot; style=&quot;position:relative;&quot;&gt;Stubs&lt;a href=&quot;#Stubs&quot; aria-label=&quot;Stubs permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dummies&lt;/strong&gt;: These don&apos;t do anything. Nor are they used during a test. These are objects that are just used to fill up parameter lists so that a constructor, function, or method will execute. They can often be &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt; or empty-string.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stubs&lt;/strong&gt;: A stub is a dependency that we can configure to return different values in &lt;a href=&quot;/articles/oop-design-principles/command-query-separation&quot;&gt;query-like&lt;/a&gt; scenarios. This generally takes some effort to do.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fakes&lt;/strong&gt;: A fake is practically the same thing as a stub. They only differ in the sense that we create a fake to sub in for a dependency that doesn&apos;t exist yet. This can be done very quickly.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;When-to-use-each&quot; style=&quot;position:relative;&quot;&gt;When to use each?&lt;a href=&quot;#When-to-use-each&quot; aria-label=&quot;When to use each permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The general rule of thumb is that you should:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Use mocks for commands, use stubs for queries&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;However, there are more specific rules as well depending on the type of test you&apos;re writing. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unit tests (domain layer objects)&lt;/strong&gt;: Don&apos;t use mocks. Use stubs when necessary.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use case tests (unit test)&lt;/strong&gt;: Only use mocks to assert that &lt;span class=&quot;special-green&quot;&gt;commands&lt;/span&gt; were invoked against dependencies. Use stubs when necessary.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contract tests (integration)&lt;/strong&gt;: You&apos;re testing the contract between a &lt;a href=&quot;/wiki/managed-vs-unmanaged-dependencies/#Managed-dependencies&quot;&gt;managed dependency&lt;/a&gt; like your application database. Don&apos;t mock anything. Ensure that the &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;repository&lt;/a&gt; (the adapter to your database) can do everything that the interface (the contract) says it needs to be able to do.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration tests (incoming adapter tests)&lt;/strong&gt;: You&apos;re testing that the incoming communication mechanism (such as an HTTP request from a web server, GraphQL API, webhook or some other incoming port) calls the correct application layer use case. Don&apos;t mock the HTTP calls. Use an HTTP testing framework like &lt;a href=&quot;https://www.npmjs.com/package/supertest&quot;&gt;Supertest&lt;/a&gt; to make real requests to your application. You can stub the response for the use case because the behavior is covered in use case tests.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration tests (outgoing adapter tests)&lt;/strong&gt;: You&apos;re testing that you can connect to an &lt;a href=&quot;/wiki/managed-vs-unmanaged-dependencies/#Unmanaged-dependencies&quot;&gt;unmanaged dependency&lt;/a&gt; like Stripe, PayPal, an email-sending service, or some piece of infrastructure shared between several applications in your enterprise (like AWS SES). While writing a test against the real thing is better, &lt;a href=&quot;/wiki/managed-vs-unmanaged-dependencies/#Integration-testing-unmanaged-dependencies&quot;&gt;choose one of these options&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;End-to-end tests&lt;/strong&gt;: Treat the entire application like a black box. Don&apos;t mock anything. If you&apos;re using 3rd party APIs like Stripe or PayPal for example, if provided, use their &lt;em&gt;Sandbox Environments&lt;/em&gt; (&lt;a href=&quot;https://stripe.com/docs/testing&quot;&gt;see Stripe sandbox docs&lt;/a&gt;, &lt;a href=&quot;https://developer.paypal.com/developer/accounts/&quot;&gt;see Paypal sandbox docs&lt;/a&gt;). Use these specifically for your E2E tests instead of mocking them out entirely. Why? Because we want to test against the most production-like environment as possible. You can, however, stubs (see the Builder pattern) to clean up the creation of request data if necessary.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Additional-testing-principles&quot; style=&quot;position:relative;&quot;&gt;Additional testing principles&lt;a href=&quot;#Additional-testing-principles&quot; aria-label=&quot;Additional testing principles permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Do not perform assertions on queries; assert the result instead&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For example, in a &lt;a href=&quot;/articles/test-driven-development/use-case-tests-mocking/&quot;&gt;use case test&lt;/a&gt;, the following type of assertion is a violation of the rule and can lead to brittle tests. This is due to the fact that a query is an implementation detail.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// While testing that a `createOffer` use case in a vinyl-trading application&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// can successfully save and email the vinyl owner.&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mockTraderRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;getTraderReputation&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;123&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mockVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;getVinylOwner&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;123&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;You should be able to create a mock with merely an interface (the contract)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you have to manually define the implementation for your mock every single time you want to use one, you&apos;ll run into the situation where everytime you add or change a method on your interface, you&apos;ll have to update all your mock implementations in your test files.&lt;/p&gt;
&lt;p&gt;Take a look at &quot;&lt;a href=&quot;/articles/test-driven-development/how-to-mock-typescript/&quot;&gt;How to Mock without Providing an Implementation in TypeScript&lt;/a&gt;&quot;. We explore this problem and provide a solution using ts-auto-mock.&lt;/p&gt;
&lt;!-- Use stubs when you&apos;re 

### Specifically, when to use stubs

In a layered architecture, we use stubs in the following of 

1. Incoming adapters (GraphQL, REST, webhook calls)
2. Managed outgoing adapters (application database)
3. Unmanaged outgoing adapters (message bus, email/notification service)
4. The application core (use cases)
5. Domain objects (entities, value objects, domain services) --&gt;</content:encoded></item><item><title><![CDATA[How to Mock without Providing an Implementation in TypeScript]]></title><description><![CDATA[I've been spending some time attempting to really understand the philosophy of testing in software design. There is a tremendous amount of…]]></description><link>https://khalilstemmler.com/articles/test-driven-development/how-to-mock-typescript/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/test-driven-development/how-to-mock-typescript/</guid><pubDate>Sat, 07 Aug 2021 15:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;special-quote&quot;&gt;🌱 This blog post hasn&apos;t fully bloomed. It&apos;s very likely to change over the next little while.&lt;/p&gt;
&lt;p&gt;I&apos;ve been spending some time attempting to really understand the philosophy of testing in software design. There is a tremendous amount of varying thought, but my goal is to find some &lt;em&gt;truth&lt;/em&gt; and crunch it into something digestible.&lt;/p&gt;
&lt;p&gt;A couple of the questions I&apos;ve been wrestling with are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/wiki/test-doubles/#When-to-use-each&quot;&gt;When exactly should you mock?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/wiki/test-doubles/#When-to-use-each&quot;&gt;When should you &lt;em&gt;not&lt;/em&gt; mock?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;How do you do mocking properly? &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because I use Jest as my test runner and mocking comes with it out-of-the-box, I figured I&apos;d use Jest to create my mocks and that&apos;d be it. Unfortunately, as a diligent blog reader pointed out, I wasn&apos;t actually writing mocks. I was inadvertly writing stubs and incurring the negative implications of that slight as well.&lt;/p&gt;
&lt;p&gt;Upon further research, I realized that this was an issue &lt;a target=&quot;_blank&quot; href=&quot;https://stackoverflow.com/questions/52122234/mock-a-typescript-interface-with-jest&quot;&gt;many TypeScript developers using Jest are still currently running into&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In this post, I&apos;ll explain how many of us are not actually mocking properly using Jest, what some of the implications of that are, and how to fix it.&lt;/p&gt;
&lt;h2 id=&quot;What-is-a-mock&quot; style=&quot;position:relative;&quot;&gt;What is a mock?&lt;a href=&quot;#What-is-a-mock&quot; aria-label=&quot;What is a mock permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First of all, what&apos;s a mock? &lt;/p&gt;
&lt;p&gt;The term &quot;mocking&quot; is often overloaded (we&apos;ve purposely done that here) to refer to the concept of a subbing in a dependency for a &lt;a href=&quot;/wiki/test-doubles/&quot;&gt;test double&lt;/a&gt;, which is an umbrella term for either a &quot;mock&quot; or a &quot;stub&quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/wiki/testing/test-doubles/test-doubles.svg&quot; alt=&quot;Test doubles&quot;&gt;&lt;/p&gt;
&lt;p&gt;Fundamentally, we use a mock to stand in for a dependency that we&apos;ll issue &lt;a href=&quot;/articles/oop-design-principles/command-query-separation&quot;&gt;command-like&lt;/a&gt; operations (outgoing interactions or state changes against dependencies) on. And we use stubs to provide data for query-like operations in tests.&lt;/p&gt;
&lt;h2 id=&quot;A-standard-use-case-test&quot; style=&quot;position:relative;&quot;&gt;A standard use case test&lt;a href=&quot;#A-standard-use-case-test&quot; aria-label=&quot;A standard use case test permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&apos;s a problematic example of a &lt;a href=&quot;/articles/test-driven-development/use-case-tests-mocking/&quot;&gt;use case test&lt;/a&gt; written using Jest.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
	INotificationService&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
	ITradesRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
	IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
	MakeOffer 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./makeOffer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;makeOffer&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Given a vinyl exists and is available for trade&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;When a trader wants to place an offer using money&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Then the offer should get created and an 
      email should be sent to the vinyl owner&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        
        &lt;span class=&quot;token comment&quot;&gt;// Collaborator #1 - Should be a stub object.&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// We have to provide an implementation otherwise&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// we&apos;ll get a compilation error.&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; fakeVinylRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IVinylRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          getVinylOwner&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;4&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Jim&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          isVinylAvailableForTrade&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Collaborator #2 - should be a mock&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Unfortunately, we also need to provide an implementation of the&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// interface.&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; mockTradesRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ITradesRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          saveOffer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;offer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Collaborator #3 - should also be a mock object&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Again, implementation required.&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; mockNotificationService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; INotificationService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          sendEmail&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; makeOffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MakeOffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          fakeVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
          mockTradesRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          mockNotificationService
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; makeOffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;123&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          tradeType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;money&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          amountInCents&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;35&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// We are confirming that the two command-like operations&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// have been called by looking commands invoked on the mocks.&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mockTradesRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;save&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mockNotificationService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sendEmail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let&apos;s discuss the collaborators here. &lt;/p&gt;
&lt;p&gt;The first collaborator is the &lt;code class=&quot;language-text&quot;&gt;fakeVinylRepo&lt;/code&gt;. Because this is used for &lt;em&gt;queries&lt;/em&gt;, it&apos;s not going to be a mock of any sort. I want this to be a &lt;a href=&quot;/wiki/test-doubles/#Stubs&quot;&gt;fake&lt;/a&gt; (a type of stub). &lt;/p&gt;
&lt;p&gt;The second and third collaborators are intended to be used to verify that an &quot;offer was created&quot; and that an &quot;email was sent&quot; as per the test definition. Both of those things are command-like operations that should be changing state in &lt;a href=&quot;/wiki/managed-vs-unmanaged-dependencies/&quot;&gt;dependencies&lt;/a&gt;. That means that we&apos;re looking at these things as if they&apos;re mocks.&lt;/p&gt;
&lt;h2 id=&quot;Problems&quot; style=&quot;position:relative;&quot;&gt;Problems&lt;a href=&quot;#Problems&quot; aria-label=&quot;Problems permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What&apos;s wrong with this?&lt;/p&gt;
&lt;h3 id=&quot;My-mocks-are-actually-stubs&quot; style=&quot;position:relative;&quot;&gt;My mocks are actually stubs&lt;a href=&quot;#My-mocks-are-actually-stubs&quot; aria-label=&quot;My mocks are actually stubs permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As was pointed out to me by one blog reader, if you need to provide an implementation to your mock, you&apos;re not really creating a mock anymore - you&apos;re creating a stub. This makes sense if we really think about &lt;a href=&quot;/wiki/test-doubles&quot;&gt;the definition of a mock and a stub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I tried removing the implementation from my design, but I found that with Jest, I couldn&apos;t do that and keep my code happy and compiling.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; mockTradesRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ITradesRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Error&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I &lt;em&gt;could&lt;/em&gt; just &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt; type this, but I don&apos;t want to. I&apos;m documenting using an interface to help future test readers understand that what is being passed in here is of type &lt;code class=&quot;language-text&quot;&gt;IVinylRepo&lt;/code&gt;, not just &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt; object. What I needed was the ability to merely specify the &lt;code class=&quot;language-text&quot;&gt;interface&lt;/code&gt; of a mock object and let the testing framework create the mock for me.&lt;/p&gt;
&lt;p&gt;Unfortunately, I&apos;ve yet to find a way to do this with Jest. It seems like I have to provide an implementation. This is problematic, because as one StackOverflow user commented, &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Although it&apos;s technically true that a mock just needs to have the same shape as the interface, that misses the whole point. The whole point is to have a convenient way to generate a mock given an interface, so that developers don&apos;t have to manually create mock classes just to, say, stub out a single function out of a dozen methods every time you need to run a test.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;Brittle-test-code&quot; style=&quot;position:relative;&quot;&gt;Brittle test code&lt;a href=&quot;#Brittle-test-code&quot; aria-label=&quot;Brittle test code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The larger issue here is that if we have to provide an implementation for every test double in our test files, every time we go and add a new method to the interface for an adapter, our tests will break until we go back and update all the mocks and stubs in our tests. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ITradesRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;getOfferById&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Offer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; None&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// New method breaks tests&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;saveOffer&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;offer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Offer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We obviously can&apos;t have that.&lt;/p&gt;
&lt;h2 id=&quot;Mocking-and-stubbing-with-nothing-but-an-interface-using-ts-auto-mock&quot; style=&quot;position:relative;&quot;&gt;Mocking and stubbing with nothing but an interface using ts-auto-mock&lt;a href=&quot;#Mocking-and-stubbing-with-nothing-but-an-interface-using-ts-auto-mock&quot; aria-label=&quot;Mocking and stubbing with nothing but an interface using ts auto mock permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&apos;ve stumbled upon a wonderful library written by the &lt;a href=&quot;https://github.com/Typescript-TDD&quot;&gt;TypeScript-TDD&lt;/a&gt; community called &lt;a href=&quot;https://github.com/Typescript-TDD/ts-auto-mock&quot;&gt;ts-auto-mock&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With ts-auto-mock, we avoid the problem of needing to provide an implementation for each mock and stub. We just give it the interface and it fills that out for us.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// makeOffer.spec.ts&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ITradesRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MakeOffer &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./makeOffer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createMock &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ts-auto-mock&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; NotificationsSpy &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./notificationSpy&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 

&lt;span class=&quot;token comment&quot;&gt;// Don&apos;t care about providing implementations for the stubs&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// and the compiler won&apos;t yell at us either&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; fakeVinylRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; createMock&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IVinylRepo&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Here&apos;s our first mock object&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; mockTradesRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; createMock&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ITradesRepo&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// And our second mock object.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// We&apos;ve also written this as a spy instead. You&apos;ll see why&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// in a moment.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; notificationServiceSpy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NotificationsSpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 

&lt;span class=&quot;token comment&quot;&gt;// This compiles! &lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; makeOffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MakeOffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  fakeVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
  mockTradesRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  notificationServiceSpy
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Our assertions&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mockTradesRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;saveOffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;notificationsSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getEmailsSent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ts-auto-mock provides trivial implementations of all of methods on the interface at runtime, so if within my &lt;code class=&quot;language-text&quot;&gt;MakeOffer&lt;/code&gt; use case, I was to call any of the methods on the test doubles (mocks and stubs), it wouldn&apos;t result in a runtime failure.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// makeOffer.ts&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MakeOffer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; vinylRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; tradesRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ITradesRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; notificationService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; INotificationService&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// This is just to demonstrate that none of these methods exist yet, &lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// but we can still call them and verify that they work&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// in our tests! &lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; owner &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getVinylOwner&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; available &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isVinylAvailableForTrade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tradesRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;saveOffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;123&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      tradeType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;money&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      amountInCents&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;35&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;notificationService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You&apos;ll also notice in the test file that I&apos;ve written the &lt;code class=&quot;language-text&quot;&gt;notificationService&lt;/code&gt; as a spy instead. Generally, you use a spy when you want more control as to how you&apos;ll verify that the state-changing command was issued on a dependency.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// modules/notifications/mocks/notificationSpy.ts&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; INotificationService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./makeOffer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NotificationSpy&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;INotificationService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; emailsSent&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailsSent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sendEmail&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailsSent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getEmailsSent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailsSent&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Because this is a traditional &lt;em&gt;concrete-class-implementing-an-interface&lt;/em&gt;, if I add new methods to the &lt;code class=&quot;language-text&quot;&gt;INotificationService&lt;/code&gt;, I&apos;ll have to update it here, probably with a &lt;code class=&quot;language-text&quot;&gt;throw new Error(&amp;#39;Not yet implemented&amp;#39;)&lt;/code&gt; statement until I figure out how it should work in the spy. &lt;/p&gt;
&lt;p&gt;This could be better because I can maintain this single spy and use it for various tests, but I&apos;m still working out how we can use ts-auto-mock for other use cases like this.&lt;/p&gt;
&lt;h2 id=&quot;Summary&quot; style=&quot;position:relative;&quot;&gt;Summary&lt;a href=&quot;#Summary&quot; aria-label=&quot;Summary permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;In TypeScript, we&apos;re forced to provide an implementation for test doubles in Jest. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;By definition of mocks and stubs, this means each test double is a stub.&lt;/li&gt;
&lt;li&gt;It also means our tests and test doubles will be brittle since adding new methods to an interface requires changing the test doubles.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use &lt;a href=&quot;https://github.com/Typescript-TDD/ts-auto-mock&quot;&gt;ts-auto-mock&lt;/a&gt; to create pure mock objects using merely an interface&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For an example, with Jest see &lt;a href=&quot;https://github.com/Typescript-TDD/jest-ts-auto-mock&quot;&gt;jest-ts-auto-mock&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thank you &lt;a href=&quot;https://github.com/uittorio&quot;&gt;Vittorio Guerriero&lt;/a&gt;!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[When to Use Mocks: Use Case Tests]]></title><description><![CDATA[If you're not familiar with mocking, it's a pretty controversial topic in testing.  Mocking implies the use of some sort of test double…]]></description><link>https://khalilstemmler.com/articles/test-driven-development/use-case-tests-mocking/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/test-driven-development/use-case-tests-mocking/</guid><pubDate>Wed, 04 Aug 2021 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;If you&apos;re not familiar with mocking, it&apos;s a pretty controversial topic in &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/introduction-to-tdd/#Classic-Inside-OutChicago-and-Mockist-Outside-InLondon-TDD&quot;&gt;testing&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Mocking implies the use of some sort of &lt;em&gt;test double&lt;/em&gt; which we sub in for &lt;strong&gt;real&lt;/strong&gt; components. When you&apos;re testing, you obviously want to get as much confidence as possible that your code is working correctly, right? So then, why would we bother using mocks if all it&apos;s going to do is reduce your confidence?&lt;/p&gt;
&lt;p&gt;A reader sent in a question expressing his concern to me recently. He said,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Mocking vs stubbing has always caused conflict with me, because to me it seems that mocking violates the fact that we are only interested in testing the external api/contract of a code module as it tests whether specific internal functions were called. If I am not mistaken, when we desire to test a function/method, we are not interested in what other functions/methods it calls, but only in providing the correct output. Please correct me if I am wrong.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You’re right on the money. Mocking &lt;em&gt;alone&lt;/em&gt; isn&apos;t the best way to test an application. However, mocking &lt;em&gt;does&lt;/em&gt; have benefits when used as a part of a larger testing strategy. Let&apos;s explore.&lt;/p&gt;
&lt;h2 id=&quot;Prerequisites&quot; style=&quot;position:relative;&quot;&gt;Prerequisites&lt;a href=&quot;#Prerequisites&quot; aria-label=&quot;Prerequisites permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;You&apos;re familiar with &lt;a href=&quot;/wiki/test-doubles&quot;&gt;test doubles&lt;/a&gt; and know the &lt;a href=&quot;/wiki/test-doubles&quot;&gt;the difference between mocks and stubs&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;The-correct-conceptual-model-of-OO&quot; style=&quot;position:relative;&quot;&gt;The correct conceptual model of OO&lt;a href=&quot;#The-correct-conceptual-model-of-OO&quot; aria-label=&quot;The correct conceptual model of OO permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We have to constrain this discussion to the idea of OO, because mocking is a lot less useful in FP. It’s just an entirely different conceptual model.&lt;/p&gt;
&lt;p&gt;The conceptual model you should have with OO is one of a “web of objects”, or like as Alan Kay had initially imagined, cell biology. Think of objects as cells each with their own tiny little “mini-computers” and encapsulated state within them. You can even think of it as routers in a computer network.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/use-case-tests/web-of-objects.png&quot; alt=&quot;Web of objects&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;How you should really think of OO, as a &quot;Web of Objects&quot;&lt;/p&gt;
&lt;p&gt;Behaviour is realized through the messages. For example, cell A tells cell B to do something (which may delegate some work to cell C without cell A needing to know that happened).&lt;/p&gt;
&lt;h2 id=&quot;What-do-we-have-to-test&quot; style=&quot;position:relative;&quot;&gt;What do we have to test?&lt;a href=&quot;#What-do-we-have-to-test&quot; aria-label=&quot;What do we have to test permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In a layered architecture, we have to test:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span class=&quot;special-green&quot;&gt;Incoming adapters (GraphQL, REST, incoming webhooks)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Managed outgoing adapters (application database)&lt;/li&gt;
&lt;li&gt;Unmanaged outgoing adapters (message bus, email/notification service or other public API calls)&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;special-green&quot;&gt;The application core (use cases)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Domain objects (entities, value objects, domain services)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Because each of these tests need to verify different things, we have to use &lt;a href=&quot;/wiki/test-doubles#When-to-use-each&quot;&gt;different testing strategies for each one&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let&apos;s focus specifically on #4, testing the application core use cases. But first, we have to discuss some of the underlying philosophy for &lt;a href=&quot;/wiki/test-doubles#When-to-use-each&quot;&gt;how to use test doubles correctly&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Command-query-separation&quot; style=&quot;position:relative;&quot;&gt;Command-query separation&lt;a href=&quot;#Command-query-separation&quot; aria-label=&quot;Command query separation permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use cases are the features of our applications. If you&apos;ll recall, features can be either commands or queries, as per the &lt;a href=&quot;https://khalilstemmler.com/articles/oop-design-principles/command-query-separation/&quot;&gt;CQS principle&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Commands are unique from queries in the sense that they perform a state change. It could be saving an entity to a database, queuing an email, saving an event to some event storage, and so on. &lt;/p&gt;
&lt;p&gt;Ultimately the rule with test doubles with respect to CQS is that we:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Use mocks for commands, use stubs for queries&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And when it comes to performing assertions, we:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Do not perform assertions on queries. Assert only results and that commands were invoked using mocks.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;These rules are in place to ensure that your tests aren&apos;t susceptible to ripple. It&apos;s to prevent you from writing the brittle sort of test that asserts against implementation details. And since query-like operations can be seen as implementation details, we create brittle tests when we assert against them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In testing a use case, our goal is to test 1) that the outgoing interactions - the commands - were issued from our application core, and 2) we get the intended outcome for the scenario&lt;/strong&gt;. &lt;/p&gt;
&lt;h2 id=&quot;Writing-a-use-case-test&quot; style=&quot;position:relative;&quot;&gt;Writing a use case test&lt;a href=&quot;#Writing-a-use-case-test&quot; aria-label=&quot;Writing a use case test permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&apos;s assume you have a &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use case&lt;/a&gt; that you need to implement using TDD. You even have the functional requirements written out using Gherkin in Given-When-Then format.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;gherkin&quot;&gt;&lt;pre class=&quot;language-gherkin&quot;&gt;&lt;code class=&quot;language-gherkin&quot;&gt;&lt;span class=&quot;token feature&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Feature:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Make offer&lt;/span&gt;

&lt;/span&gt;&lt;span class=&quot;token scenario&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Scenario:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Making a monetary offer&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token atrule&quot;&gt;Given&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;a&lt;/span&gt; vinyl exists and is available for trade
	&lt;span class=&quot;token atrule&quot;&gt;When&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;a&lt;/span&gt; trader wants to place an offer using money
	&lt;span class=&quot;token atrule&quot;&gt;Then&lt;/span&gt; the offer should get created 
	&lt;span class=&quot;token atrule&quot;&gt;And&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;an&lt;/span&gt; email should be sent to the vinyl owner&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Fantastic. We know, at a high-level, from the user&apos;s perspective, &lt;strong&gt;one of many scenarios for this use case that we&apos;ll need to test&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;As you likely know, the TDD process is to start with a failing test, make it pass, and then refactor it. Where a lot of developers get stuck is trying to figure out &lt;em&gt;how exactly&lt;/em&gt; to write tests for this, especially because the solution is going to involve databases, external services, and other infrastructural concerns that will slow down tests and &lt;strong&gt;cause it to no longer be a unit test&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What&apos;s &lt;em&gt;not&lt;/em&gt; a unit test?&lt;/strong&gt;: Michael Feathers says a test is not a unit test if:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It talks to the database&lt;/li&gt;
&lt;li&gt;It communicates across the network&lt;/li&gt;
&lt;li&gt;It touches the file system&lt;/li&gt;
&lt;li&gt;It can’t run at the same time as any of your other unit tests&lt;/li&gt;
&lt;li&gt;You have to do special things to your environment (such as editing config files) to run it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This constraint moves our discussion to the two general flavours of TDD - two ways we can write tests: inside-out and outside-in. &lt;/p&gt;
&lt;h3 id=&quot;Outside-in-vs-inside-out&quot; style=&quot;position:relative;&quot;&gt;Outside-in vs inside-out&lt;a href=&quot;#Outside-in-vs-inside-out&quot; aria-label=&quot;Outside in vs inside out permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Inside-out&lt;/strong&gt; — Most of us are familiar with this. It&apos;s when we start from the inside layers where code is pure and doesn&apos;t involve infrastructure. We unit test &lt;em&gt;outwards&lt;/em&gt;. This is typically what we think of when we consider regular unit tests. It&apos;s also known as Classic TDD. You can see a demonstration of this &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/introduction-to-tdd/#Demonstration-Classic-TDD--Palindrome-Example&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Outside-in&lt;/strong&gt; — This is when we start from the outer boundary, have some understanding of the &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/organizing-app-logic/&quot;&gt;layers of our application&lt;/a&gt;, and code &lt;em&gt;inwards&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/use-case-tests/outside-in-inside-out-tdd.svg&quot; alt=&quot;Outside-in Inside-Out TDD&quot;&gt;&lt;/p&gt;
&lt;p&gt;If we&apos;re to start at the use case boundary, it&apos;s impossible for us to write a unit test with the &lt;strong&gt;inside-out&lt;/strong&gt; approach. Since we rely on infrastructure (like databases, web services, and external services), we will fundamentally break a rule of unit tests. Use cases test the &lt;em&gt;core application functionality&lt;/em&gt;. They fetch domain objects so that inner layer objects (domain) can execute the &lt;a href=&quot;https://khalilstemmler.com/articles/software-professionalism/accidental-and-essential-complexity/&quot;&gt;essential complexity&lt;/a&gt; of the problem at hand. We want these tests to be fast - not painful, show, flaky, and hard to configure.&lt;/p&gt;
&lt;p&gt;To write a use case test (that can still technically be seen as a unit test) means we have to use the outside-in approach (the mockist approach). &lt;/p&gt;
&lt;h3 id=&quot;Starting-with-the-outcomes-commandsstate-changes&quot; style=&quot;position:relative;&quot;&gt;Starting with the outcomes (commands/state-changes)&lt;a href=&quot;#Starting-with-the-outcomes-commandsstate-changes&quot; aria-label=&quot;Starting with the outcomes commandsstate changes permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;With any test, we have to &lt;span class=&quot;special-green&quot;&gt;stop and think about the outcomes first&lt;/span&gt;. These will be either &lt;em&gt;command&lt;/em&gt;-like operations or the output result (success or failure) returned from the use case. &lt;/p&gt;
&lt;p&gt;First of all, we expect the use case to be successful in this scenario, so there&apos;s that.&lt;/p&gt;
&lt;p&gt;But if we look back to our acceptance criteria for this test, we&apos;ll notice that are two commands:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the offer should get created &lt;/li&gt;
&lt;li&gt;an email should be sent to the vinyl owner&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some TDD-practioners advocate for starting with the &lt;em&gt;assert&lt;/em&gt; phase of the &quot;arrange-act-assert&quot; structure of a test. The reason? Often, when we start with creating the objects, it&apos;s a lot harder to maintain &lt;a href=&quot;/wiki/yagni/&quot;&gt;YAGNI&lt;/a&gt; and it forces the design into things that aren&apos;t actually necessary for us to accomplish the behavior. Once you get comfortable writing tests using TDD, I also advise this technique.&lt;/p&gt;
&lt;p&gt;Here&apos;s what the start of our outside-in test could look like.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// modules/trading/useCases/makeOffer/makeOffer.spec.ts&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;makeOffer&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Given a vinyl exists and is available for trade&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;When a trader wants to place an offer using money&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Then the offer should get created and an email should be sent to the vinyl owner&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Arrange&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Act&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Assert &lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isSuccess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                    &lt;span class=&quot;token comment&quot;&gt;// result&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mockTradesRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;saveOffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// outcome &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;notificationsSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getEmailsSent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// outcome&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;notificationsSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emailWasSentFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;offerId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                      &lt;span class=&quot;token comment&quot;&gt;// outcome&lt;/span&gt;&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At this point, we are very much in the &lt;span class=&quot;red-text&quot;&gt;red&lt;/span&gt; of the &lt;em&gt;red-green-refactor loop&lt;/em&gt;. I&apos;m referring to objects that don&apos;t exist, but that&apos;s completely OK, because that&apos;s what we&apos;re supposed to do. We&apos;re not too concerned about &lt;em&gt;how&lt;/em&gt; we&apos;ll make this work. At this point, we&apos;re concerned about &lt;em&gt;how we&apos;ll know&lt;/em&gt; that it worked. That&apos;s the big thing you get when you write test-first.&lt;/p&gt;
&lt;p&gt;Here&apos;s what we&apos;re doing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I&apos;m assuming that we&apos;ll get a &lt;a href=&quot;/articles/enterprise-typescript-nodejs/handling-errors-result-class/&quot;&gt;result object&lt;/a&gt; back from the use case. I&apos;m assuming this result will be successful.&lt;/li&gt;
&lt;li&gt;I&apos;m also writing about a collaborator called a &lt;code class=&quot;language-text&quot;&gt;mockTradesRepo&lt;/code&gt;, and because one of the requirements is that the &quot;offer should get created&quot;, I know that the command (the object-oriented message we&apos;ll send to a &lt;em&gt;real&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;TradesRepo&lt;/code&gt;) will be called &lt;code class=&quot;language-text&quot;&gt;saveOffer&lt;/code&gt;. We expect that to have been called. &lt;/li&gt;
&lt;li&gt;Lastly, I used my imagination to consider how I could ascertain that an email was sent and that it was sent in the correct context. If we return the &lt;code class=&quot;language-text&quot;&gt;offerId&lt;/code&gt; in the result, we can link that to the email. I need a mock object here, but I know that a &lt;em&gt;hand-rolled&lt;/em&gt; mock object, one that we write custom test methods on is actually called a &lt;a href=&quot;/wiki/test-doubles#Mocks&quot;&gt;spy&lt;/a&gt;, we name the &lt;code class=&quot;language-text&quot;&gt;notificationsRepo&lt;/code&gt; mock object a &lt;code class=&quot;language-text&quot;&gt;notificationsSpy&lt;/code&gt; accordingly.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Acting-out-the-behavior&quot; style=&quot;position:relative;&quot;&gt;Acting out the behavior&lt;a href=&quot;#Acting-out-the-behavior&quot; aria-label=&quot;Acting out the behavior permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Continuing to work backwards, we&apos;ll act out the behavior to make this thing work. I&apos;m specifically focused on the &lt;em&gt;when&lt;/em&gt; part of the Given-When-Then statement: &quot;When a trader wants to place an offer using money&quot;.&lt;/p&gt;
&lt;p&gt;I write something like the following:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// modules/trading/useCases/makeOffer/makeOffer.spec.ts&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;makeOffer&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Given a vinyl exists and is available for trade&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;When a trader wants to place an offer using money&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Then the offer should get created and an email should be sent to the vinyl owner&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Arrange&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Act&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; makeOffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;123&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          tradeType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;money&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          amountInCents&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;35&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Assert &lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isSuccess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                    
        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mockTradesRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;saveOffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;       
        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;notificationsSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getEmailsSent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;notificationsSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emailWasSentFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;offerId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                     
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So far so good. &lt;/p&gt;
&lt;h3 id=&quot;Create-the-subject-and-collaborators-in-the-arrange-phase&quot; style=&quot;position:relative;&quot;&gt;Create the subject and collaborators in the arrange phase&lt;a href=&quot;#Create-the-subject-and-collaborators-in-the-arrange-phase&quot; aria-label=&quot;Create the subject and collaborators in the arrange phase permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There are a couple of objects we need to create here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Subject: The &lt;code class=&quot;language-text&quot;&gt;MakeOffer&lt;/code&gt; use case which returns a result.&lt;/li&gt;
&lt;li&gt;Collaborator #1: The &lt;code class=&quot;language-text&quot;&gt;TradesRepo&lt;/code&gt; (which we will mock).&lt;/li&gt;
&lt;li&gt;Collaborator #2: The &lt;code class=&quot;language-text&quot;&gt;NotificationService&lt;/code&gt; (which we will mock with a spy)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&apos;s where we merely create these objects and focus on getting our code to at least compile.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// modules/trading/useCases/makeOffer/makeOffer.spec.ts&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ITradesRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MakeOffer &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./makeOffer&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; NotificationsSpy &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./notificationSpy&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createMock &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ts-auto-mock&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;makeOffer&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Given a vinyl exists and is available for trade&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;When a trader wants to place an offer using money&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Then the offer should get created and an email should be sent to the vinyl owner&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token comment&quot;&gt;// Arrange&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; mockTradesRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; createMock&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ITradesRepo&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; notificationsSpy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NotificationsSpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; makeOffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MakeOffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          mockTradesRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          notificationsSpy&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Act&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; makeOffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;123&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          tradeType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;money&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          amountInCents&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;35&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Assert &lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isSuccess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                    
        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mockTradesRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;saveOffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;       
        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;notificationsSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getEmailsSent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;notificationsSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emailWasSentFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;offerId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                     
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we have the interface for the &lt;code class=&quot;language-text&quot;&gt;TradeRepo&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ITradesRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;saveOffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;offer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And here we have the spy for the &lt;code class=&quot;language-text&quot;&gt;NotificationsService&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NotificationsSpy&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;INotificationService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; emailsSent&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailsSent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sendEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailsSent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getEmailsSent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailsSent&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;emailWasSentFor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getEmailsSent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;No emails sent&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getEmailsSent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;More than one email sent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getEmailsSent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;originatingId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;NotificationService&lt;/code&gt; interface:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Email &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; originatingId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;INotificationService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;sendEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And a minimal, trivial implementation of the &lt;code class=&quot;language-text&quot;&gt;MakeOffer&lt;/code&gt; use case.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// modules/trading/useCases/makeOffer/makeOffer.ts&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MakeOffer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; tradesRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ITradesRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; notificationService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; INotificationService&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That should let our code compile. &lt;/p&gt;
&lt;p&gt;We&apos;re still pretty &lt;span class=&quot;red-text&quot;&gt;red&lt;/span&gt; but now, we can focus on getting to &lt;span class=&quot;special-green&quot;&gt;green&lt;/span&gt;.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;ts-auto-mock&lt;/b&gt;: You may notice that we&apos;re using &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/Typescript-TDD/ts-auto-mock&quot;&gt;ts-auto-mock&lt;/a&gt; instead of Jest to create mocks. I wrote about why we&apos;re doing this in &lt;a href=&quot;/articles/test-driven-development/how-to-mock-typescript/&quot;&gt;How to Mock without Providing an Implementation in TypeScript&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Adding-stub-objects&quot; style=&quot;position:relative;&quot;&gt;Adding stub objects&lt;a href=&quot;#Adding-stub-objects&quot; aria-label=&quot;Adding stub objects permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As we start to implement the &lt;code class=&quot;language-text&quot;&gt;MakeOffer&lt;/code&gt; use case, we realize that we can&apos;t really do this without the existence of a &lt;code class=&quot;language-text&quot;&gt;VinylRepo&lt;/code&gt; of some sort to actually &lt;em&gt;fetch&lt;/em&gt; the vinyl entity and determine if it&apos;s available for trade or not.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// vinylRepo.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IVinylRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getVinylOwner&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Trader &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Nothing&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;isVinylAvailableForTrade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// modules/trading/useCases/makeOffer/makeOffer.spec.ts&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ITradesRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MakeOffer &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./makeOffer&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; NotificationsSpy &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./notificationSpy&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createMock &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ts-auto-mock&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;makeOffer&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Given a vinyl exists and is available for trade&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;When a trader wants to place an offer using money&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Then the offer should get created and an email should be sent to the vinyl owner&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Arrange&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; fakeVinylRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; createMock&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IVinylRepo&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; mockTradesRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; createMock&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ITradesRepo&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; notificationsSpy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NotificationsSpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; makeOffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MakeOffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          fakeVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;          mockTradesRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          notificationsSpy&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Act&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; makeOffer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;123&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          tradeType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;money&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          amountInCents&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;35&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Assert &lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isSuccess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                    
        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mockTradesRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;saveOffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;       
        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;notificationsSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getEmailsSent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
        &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;notificationsSpy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emailWasSentFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;offerId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                     
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And the use case changes to:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// modules/trading/useCases/makeOffer/makeOffer.ts&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MakeOffer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; vinylRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; tradesRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ITradesRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; notificationService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; INotificationService&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It&apos;s good that we&apos;re discovering this later &lt;em&gt;after&lt;/em&gt; we&apos;ve already written out what we&apos;re going to assert: the command-like operations and the result for the use case. Sometimes, when we start with creating the objects in the &quot;arrange&quot; phase, we&apos;re tempted to assume that the objects which perform &lt;em&gt;queries&lt;/em&gt; are somehow important to validating the correctness of our tests. &lt;/p&gt;
&lt;p&gt;For example, in an earlier version of this very post, I was doing this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fakeVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;getVinylOwner&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;123&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This leads to brittle, hard-to-maintain tests because the queries have nothing to do with the outcomes (state changes + result). If the implementation changes, then we experience ripple and up having to change our tests. And that&apos;s yucky. Special thank you to Steve in the comments section for pointing this out. &lt;/p&gt;
&lt;h3 id=&quot;Double-loop-TDD-and-turning-this-test-green&quot; style=&quot;position:relative;&quot;&gt;Double loop TDD and turning this test green&lt;a href=&quot;#Double-loop-TDD-and-turning-this-test-green&quot; aria-label=&quot;Double loop TDD and turning this test green permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Great start.&lt;/p&gt;
&lt;p&gt;Is this enough? Absolutely not. This test will not pass until we have gone in, fleshed out the rest of the &lt;code class=&quot;language-text&quot;&gt;MakeOffer&lt;/code&gt; use case, and probably also end up creating &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/entities/&quot;&gt;domain entities&lt;/a&gt; for &lt;code class=&quot;language-text&quot;&gt;Email&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Offer&lt;/code&gt;, and probably &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; too (each of which we should be unit testing with the inside-out approach).&lt;/p&gt;
&lt;p&gt;Some call this approach to TDD &lt;em&gt;double loop TDD&lt;/em&gt;. You have an outer loop (the one that we&apos;ve been writing in this post so far) which shapes the way the use case could work and exercises the scenarios (these are often the acceptance tests), and you have the inner loop which ensures that the smaller, pure domain objects are properly tested as well.&lt;/p&gt;
&lt;p&gt;This means that the outer TDD loop stays red for much longer than the inner TDD loop. But once both the outer and inner loops pass, you&apos;re done that scenario.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/use-case-tests/double-loop.png&quot; alt=&quot;Double Loop TDD&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is a powerful tool for your toolbox, but it &lt;strong&gt;is important to remember that it is not mutually exclusive&lt;/strong&gt; to the classic (chigago-Kent Beck) style of TDD where you pass in real objects. &lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Integration tests and managed/unmanaged dependencies&lt;/b&gt;: There is much to test in a clean (hexagonal, onion, ports and adapters, layer) architecture and it can get pretty complicated to explain. There are incoming adapters and outgoing adapters. Incoming adapters are things like GraphQL and REST. Outgoing adapters are things like databases or facades that we&apos;re written to external services like Stripe and so on. Each of these out-of-process, external dependencies are said to be either a &lt;a href=&quot;/wiki/managed-vs-unmanaged-dependencies/&quot;&gt;managed or unmanaged dependency&lt;/a&gt;. Depending on the type, we write different kinds of tests for them. For example, &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;repository objects (adapters to our application database)&lt;/a&gt;, are &lt;i&gt;managed&lt;/i&gt; &lt;i&gt;output adapters&lt;/i&gt;. The best way to test it is to confirm that it adheres to contract of the interface - that is, to perform a &lt;i&gt;contract test&lt;/i&gt;. Read about &lt;a href=&quot;/wiki/managed-vs-unmanaged-dependencies/&quot;&gt;managed and unmanaged dependencies here &lt;/a&gt; and &lt;a href=&quot;/articles/test-driven-development/use-case-tests-mocking/#Part-of-a-larger-testing-strategy&quot;&gt;what each type of test in a testing strategy is for&lt;/a&gt;, below.&lt;/p&gt;
&lt;h3 id=&quot;Using-stubs-to-force-code-paths&quot; style=&quot;position:relative;&quot;&gt;Using stubs to force code paths&lt;a href=&quot;#Using-stubs-to-force-code-paths&quot; aria-label=&quot;Using stubs to force code paths permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We know that most use cases have typically one happy path and &lt;strong&gt;numerous sad paths.&lt;/strong&gt; By adjusting the input data and setting up &lt;a href=&quot;/wiki/test-doubles/#Stubs&quot;&gt;stubs&lt;/a&gt; to return different data in different contexts, we get the ability to force our code through paths to see if our use cases return the correct error result (on failure) or invoke the commands on dependencies in success cases (as we&apos;ve seen here).&lt;/p&gt;
&lt;p&gt;For example, in &lt;a href=&quot;https://github.com/stemmlerjs/ddd-forum&quot;&gt;ddd-forum&lt;/a&gt;, a forum application, &lt;a href=&quot;https://github.com/stemmlerjs/ddd-forum/blob/master/src/modules/forum/useCases/post/downvotePost/DownvotePostResponse.ts&quot;&gt;look at all the different ways&lt;/a&gt; a &lt;code class=&quot;language-text&quot;&gt;DownvotePost&lt;/code&gt; use case can fail.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Either&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Result &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../../shared/core/Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; DownvotePostErrors &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./DownvotePostErrors&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AppError &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../../shared/core/AppError&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; DownvotePostResponse &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
  DownvotePostErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;MemberNotFoundError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  DownvotePostErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AlreadyDownvotedError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  DownvotePostErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PostNotFoundError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  AppError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UnexpectedError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We have to exercise these paths with tests. So we better have the ability to be nimble with our tests.&lt;/p&gt;
&lt;h3 id=&quot;Part-of-a-larger-testing-strategy&quot; style=&quot;position:relative;&quot;&gt;Part of a larger testing strategy&lt;a href=&quot;#Part-of-a-larger-testing-strategy&quot; aria-label=&quot;Part of a larger testing strategy permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;One of the main ideas why we use a layered architecture is because of the testing options it gives us. Ultimately, you can think of your application as core and infrastructure.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/use-case-tests/core-and-infrastructure.png&quot; alt=&quot;Core and infrastructure&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you understand and enforce boundaries between these two types of code, you have a myriad of ways to set up a testing strategy for your application. Here’s one for a full stack GraphQL + React application for example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unit test&lt;/strong&gt; all smaller, pure, core components like entities, domain services, aggregates, value objects, utility classes and so on&lt;/li&gt;
&lt;li&gt;Also &lt;strong&gt;unit test&lt;/strong&gt; your use cases with mocks to confirm that we perform commands against infrastructure dependencies; use stubs to force code to go down different code paths — do this for all of your acceptance tests&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration test&lt;/strong&gt; all of your incoming and outgoing adapters (GraphQL API, database, cache, event subscribers, etc)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;End to End test&lt;/strong&gt; — from the front-end to the GraphQL API, through the database and the cache — a select few acceptance tests to get that extra bit of confidence&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With that said, your testing strategy could look something like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/use-case-tests/Test_coverage_strategy.png&quot; alt=&quot;Test coverage strategy&quot;&gt;&lt;/p&gt;
&lt;p&gt;You see? In reality, we want to use a mixture of techniques to cover as much ground as possible.&lt;/p&gt;
&lt;h2 id=&quot;Further-reaading&quot; style=&quot;position:relative;&quot;&gt;Further reaading&lt;a href=&quot;#Further-reaading&quot; aria-label=&quot;Further reaading permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://enterprisecraftsmanship.com/posts/when-to-mock/&quot;&gt;https://enterprisecraftsmanship.com/posts/when-to-mock/&lt;/a&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[Existential State Machines]]></title><description><![CDATA[Originally published in volvox vault's issue on metamorphosis.  Someone said I was a writer the other day. When the hell did that happen…]]></description><link>https://khalilstemmler.com/blogs/philosophy/existential-state-machines/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/philosophy/existential-state-machines/</guid><pubDate>Mon, 24 May 2021 15:04:10 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;Originally published in &lt;a href=&quot;https://volvoxvault.com/&quot;&gt;volvox vault&lt;/a&gt;&apos;s issue on metamorphosis. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Someone said I was a writer the other day. &lt;em&gt;When the hell did that happen?&lt;/em&gt; Over the last two years, I&apos;ve been writing blog posts - blog posts that would help my past self figure out how to stop writing code that looks like it was written by a drunken kitten (possibly more like a kitten at step six of a seven-step rehab program).&lt;/p&gt;
&lt;p&gt;When exactly did I become a writer, though? Was it when I hit CTRL+S on that first sentence? Those first few blog posts? Maybe it was when I realized I wasn&apos;t writing email newsletters for my auntie and uncle anymore. Or perhaps it was when I looked up and realized I had published over 50 blog posts, and people seem to be finding my book somewhat decent?&lt;/p&gt;
&lt;p&gt;I don&apos;t know. But I know that my focus wasn&apos;t on becoming a writer; it was about consistently doing shit that writers tend to do.&lt;/p&gt;
&lt;p&gt;Many of us have goals we&apos;d love to see come to fruition, but for whatever reason, it can be hard to stay on track. You know - you want to write a bestseller, get ripped, and play sold-out shows. But when you realize you&apos;ve been trying to write the same chapter for months, your abs don&apos;t look like a cheese grater yet, and &lt;a href=&quot;https://twitter.com/sleafordmods/status/1390654821804433413&quot;&gt;Iggy Pop isn&apos;t playing your LP for his pet bird&lt;/a&gt;, you might feel like you want to throw in the towel.&lt;/p&gt;
&lt;p&gt;Over the last 400 days or so, I&apos;ve read many books on productivity, philosophy (mainly about ethics, absurdism, and existentialism), and software design. Remarkably, I think there&apos;s a fascinating parallel to be drawn here. At least, I&apos;m going to try.&lt;/p&gt;
&lt;p&gt;In this article, I&apos;d like to do several things. First, I&apos;d like to help elucidate a better way to meet your goals by creating habits that stick. As James Clear writes in &lt;em&gt;Atomic Habits&lt;/em&gt;, habit change has more to do with identity than anything else. To convince you just how much capability you have in rewriting your beliefs, I&apos;ll rely on some of the main ideas from existentialism. I then present an exercise for fleshing out the identities, values, and principles that&apos;ll lead you to your goals. Finally, we&apos;ll wrap this up with a computer science-y conceptual model and technique to start chaining habits together tomorrow.&lt;/p&gt;
&lt;h2 id=&quot;Identity&quot; style=&quot;position:relative;&quot;&gt;Identity&lt;a href=&quot;#Identity&quot; aria-label=&quot;Identity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In James Clear&apos;s research on habits in Atomic Habits, he argues that the critical way to build habits is not to try hard but instead to identify who we want to be.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/philosophy/existential-state-machines/Frame_88.svg&quot; alt=&quot;Existential%20State%20Machines%20217d97ab438141588322d71cddb14e59/Frame_88.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;To accomplish our goals, most people compose a set of habits that they&apos;ll follow until they meet them. Only after people achieve their goals do they declare that they are the person they want to be.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Outcome-based belief: &quot;If I write this book and it sells 5000 copies, &lt;em&gt;then&lt;/em&gt; I&apos;m a writer.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Indeed, this is one way to go about it. To Clear, these are outcome-driven habits. The thing about outcome-driven habits is that we only feel motivated to continue performing them if we feel like we&apos;re getting closer to our goal. The downside of this approach is that any small failure - a step backward instead of a step forward - holds a lot of weight in our lives. Minor setbacks have the power to wreck our entire system. Minor setbacks in the outcome-driven approach to habits are the reason why people sometimes quit their dieting and weight loss routines when they notice that they&apos;ve plateaued or put weight back on.&lt;/p&gt;
&lt;p&gt;Instead, what Clear recommends is the &lt;strong&gt;identity-based&lt;/strong&gt; approach to habits.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/philosophy/existential-state-machines/Frame_89.svg&quot; alt=&quot;Existential%20State%20Machines%20217d97ab438141588322d71cddb14e59/Frame_89.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;The identity-based approach to habits is to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Decide on who we want to be&lt;/li&gt;
&lt;li&gt;Prove that we are that person with small wins, over and over&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;According to Clear&apos;s research in behavioral science and psychology, actual behavior change comes from identity change. Therefore, if we want to write a book, work backward to that goal by seeing ourselves as writers. From there, we ask ourselves, &quot;what are the types of values and principles that writers have&quot;? Clear thinking, meeting deadlines, etc. And what types of habits do they have? They probably wake up and journal every morning, right?&lt;/p&gt;
&lt;p&gt;Once we do this exercise and we start to &lt;em&gt;believe&lt;/em&gt; that we are the person we want to be, the easier it is to stick to the habits.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Identity-based belief: &quot;I am a writer, so I will do the things that writers do&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;Existentialism&quot; style=&quot;position:relative;&quot;&gt;Existentialism&lt;a href=&quot;#Existentialism&quot; aria-label=&quot;Existentialism permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you don&apos;t believe you can change your identity, your beliefs, and ultimately, your habits — well, my friend — existential philosopher Jean-Paul Sartre and his (less-buggy-eyed) antecedents have a different opinion on that.&lt;/p&gt;
&lt;p&gt;Jean-Paul Sartre taught us that &quot;existence precedes essence.&quot; That is, we exist, and then at some point, we recognize that we have a consciousness. And perhaps if we&apos;re introspective enough, at another point down the road — we also realize that we have free will, and thus the ability to determine our nature.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Every action you take is a vote for the type of person you wish to become.&quot; — Jean Paul Sartre&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;While Sartre believed that animals have a sort of predefined nature — their own immutable, unchangeable state machines (a fancy term that we&apos;re going to dive into momentarily) — he believed that we have a more privileged concept of being.&lt;/p&gt;
&lt;p&gt;Sartre and the other existentialists believed that we&apos;d be lying to ourselves (committing an act of bad faith — as they say) by pretending that we don&apos;t have the freedom to choose who and what we are — to fall victim to social pressures (&lt;em&gt;being-for-others&lt;/em&gt;) and to never take a moment to consider why one does what one does. You know, like going to college straight out of high school, going for the highest paying job, buying a house, getting married, etc. These are all well and good things if we consciously decide on them for ourselves. But to pretend we don&apos;t have a choice in the matter? That&apos;s a disservice to what it means to be human. We must choose our being (&lt;em&gt;being-for-itself&lt;/em&gt;).&lt;/p&gt;
&lt;h2 id=&quot;How-to-change-your-beliefs&quot; style=&quot;position:relative;&quot;&gt;How to change your beliefs&lt;a href=&quot;#How-to-change-your-beliefs&quot; aria-label=&quot;How to change your beliefs permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you have a couple of hours, here&apos;s an exercise I&apos;ve personally applied to my life and found incredibly helpful to put all of this reading to practice:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Write down your biggest goals in life right now (write a book, finish my album, buy a home)&lt;/li&gt;
&lt;li&gt;Ask yourself &quot;who is the type of person that would accomplish that goal&quot;?&lt;/li&gt;
&lt;li&gt;Label that person as an identity you will believe is a part of you (i.e., &quot;musician&quot;, &quot;the entrepreneur&quot;, &quot;the writer&quot;)&lt;/li&gt;
&lt;li&gt;For each identity, write down the top five values they likely hold. You can look to your role models or others who live or have lived that possess the qualities you admire.&lt;/li&gt;
&lt;li&gt;Lastly, for each value, write down the top five habits (principles) that those who possess each value are most likely to do. For example, &quot;entrepreneurs probably write a list of todos for the next day so that they know exactly what they need to do when they wake up&quot; and &quot;health-minded people probably cook the majority of their meals using real ingredients&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now you know who you want to be, you understand the virtuous action behind each identity, and you know why you&apos;re doing it. The next step is to prove to yourself that these identities are a part of you.&lt;/p&gt;
&lt;p&gt;Relax on single-mindedly hitting your goals; instead, make like the stoics, and focus on nothing else but putting in the reps and sticking to your system. Eventually, you&apos;ll see results as a side-effect.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“We are our choices.” — Jean Paul Sartre&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;Optimizing-our-behaviour&quot; style=&quot;position:relative;&quot;&gt;Optimizing our behaviour&lt;a href=&quot;#Optimizing-our-behaviour&quot; aria-label=&quot;Optimizing our behaviour permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Based on what Clear says about human behavior, cycles, and sequence, and what we know about existentialism, is it crazy to think that we get a chance to create our very own &lt;em&gt;existential state machines&lt;/em&gt;? &lt;/p&gt;
&lt;p&gt;For example, he says that going to the bathroom leads to washing and drying your hands, which then &quot;reminds you that you need to put the dirty dishes in the laundry, so you add laundry detergent to the shopping list, and so on&quot;.&lt;/p&gt;
&lt;p&gt;It&apos;s almost like there&apos;s an &lt;em&gt;encoding&lt;/em&gt; built into our brains, a default set of next steps or state changes. Wait, &lt;em&gt;state&lt;/em&gt;?&lt;/p&gt;
&lt;h3 id=&quot;State-machines&quot; style=&quot;position:relative;&quot;&gt;State machines&lt;a href=&quot;#State-machines&quot; aria-label=&quot;State machines permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In computing, we use conceptual model called &lt;em&gt;state machines&lt;/em&gt; to model the way that they should behave over time.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/philosophy/existential-state-machines/state-machine-behavior.svg&quot; alt=&quot;Existential%20State%20Machines%20217d97ab438141588322d71cddb14e59/state-machine-behavior.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;Your washing machine is actually a really great example of a state machine. It would be perfectly valid for the state of the washer to transition from &lt;code class=&quot;language-text&quot;&gt;OFF&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;ON&lt;/code&gt; and then perhaps to &lt;code class=&quot;language-text&quot;&gt;WASH&lt;/code&gt; before being &lt;code class=&quot;language-text&quot;&gt;PAUSED&lt;/code&gt; upon opening the door to sneak an extra sock or two in. Then, from &lt;code class=&quot;language-text&quot;&gt;PAUSED&lt;/code&gt;, back to &lt;code class=&quot;language-text&quot;&gt;WASH&lt;/code&gt;, before finally transitioning to &lt;code class=&quot;language-text&quot;&gt;DONE&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/philosophy/existential-state-machines/washing-machine-state-machine.svg&quot; alt=&quot;Existential%20State%20Machines%20217d97ab438141588322d71cddb14e59/washing-machine-state-machine.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;Based on what Clear says about human behavior, cycles, and sequence, and what we know about existentialism, is it crazy to think that we get a chance to create our very own &lt;strong&gt;&lt;em&gt;existential state machines&lt;/em&gt;&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;Since we get to decide what we do, is there a way to develop new state machine behavior for ourselves? Can we develop better automatic habits? Productive ones? That might be the key to some top-tier productivity if we can hack it.&lt;/p&gt;
&lt;h3 id=&quot;Habit-stacking&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Habit-stacking&lt;/strong&gt;&lt;a href=&quot;#Habit-stacking&quot; aria-label=&quot;Habit stacking permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you want to add a new habit today, one of the best ways to do it is to identify a current habit and stack your new one &lt;em&gt;right after it&lt;/em&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;After I [CURRENT HABIT], I will [NEW HABIT]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Relationships. After I sit down to drink my coffee in the morning, I will send my partner a good morning text.&lt;/li&gt;
&lt;li&gt;Planning. After I turn out the lights in the living room before bed, I will write my todo list for tomorrow morning.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Imagine what your state machine could look like. This works because it&apos;s slotting in new things around what we currently already do. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/philosophy/existential-state-machines/Group_16_(1).svg&quot; alt=&quot;Existential%20State%20Machines%20217d97ab438141588322d71cddb14e59/Group_16_(1).svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;The hard part is to stick to it — to train the synapses of our identities — to make it automatic. And to come back to it when life throws us curveballs. Clear says that the only way to make it automatic is to repeat it enough times. All the more reason to &lt;strong&gt;stick to the system&lt;/strong&gt;. &lt;strong&gt;It&apos;ll fall into place&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Before enlightenment, chop wood and carry water; after enlightenment, chop wood and carry water&quot;. — Zen proverb&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you can rewrite your beliefs (you can), you can build habits that stick and help you meet your goals. It&apos;s fun to think of your behavior as a state machine that you can frequently tune and work on. But it&apos;s even more fun to watch yourself accomplishing what you&apos;ve set out to do by merely focusing on putting in the reps and making it as enjoyable as possible.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[What Would Albert Camus Think About Software Development?]]></title><description><![CDATA[Albert Camus was a French philosopher most well known for his ideas about absurdism.  Sometimes regarded as an existentialist philosopher…]]></description><link>https://khalilstemmler.com/blogs/philosophy/camus-software-design/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/philosophy/camus-software-design/</guid><pubDate>Mon, 26 Apr 2021 15:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;special-quote&quot;&gt;🌱 This blog post hasn&apos;t fully bloomed. It&apos;s very likely to change over the next little while.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Albert_Camus&quot;&gt;Albert Camus&lt;/a&gt; was a French philosopher most well known for his ideas about &lt;a href=&quot;https://en.wikipedia.org/wiki/Absurdism&quot;&gt;absurdism&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Sometimes regarded as an existentialist philosopher among his peers like Jean-Paul Sartre and Simone De Beauvoir, he contemplated existence, the complexity of the world, and eventually declared that any meaning we find in the world is there because we have personally assigned it.&lt;/p&gt;
&lt;p&gt;As software developers, the very essence of what we do is to create something productive and meaningful within the inherent entropy of the world. &lt;/p&gt;
&lt;p&gt;As Julian Shapiro says, the world is a patchwork of systems. And in the real world, we are constantly clashing against complexities. We maneuver though clumsy incumbent systems like &quot;making friends in a new city&quot;, &quot;finding an apartment that suits our needs&quot;, and &quot;getting our driver&apos;s licenses renewed&quot;.&lt;/p&gt;
&lt;p&gt;Software cuts through this complexity. We help people get from A to B with less stress, less effort, faster, and easier.&lt;/p&gt;
&lt;p&gt;But not all complexity is equal. In our attempts to cut through complexity, we often &lt;em&gt;create&lt;/em&gt; complexity.&lt;/p&gt;
&lt;p&gt;I imagine that if Camus were a software developer, &lt;a href=&quot;https://www.goodreads.com/quotes/29516-there-is-but-one-truly-serious-philosophical-problem-and-that&quot;&gt;his famous quote about suicide&lt;/a&gt; could be reworked to say:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;There is but one truly serious philosophical software design problem and that is &lt;em&gt;maintainability&lt;/em&gt;. Judging whether code is &lt;em&gt;maintainable&lt;/em&gt; or not amounts to answering the fundamental questions of software design. All the rest — whether we should use &lt;em&gt;React, a hexagonal architecture, server-less functions&lt;/em&gt; — comes afterwards. These are games; one must first answer.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Our &lt;a href=&quot;https://wiki.solidbook.io/Introduction-872fd41c47f54a61a318c6729ed7c0bd/#this-books-approach-to-wisdom&quot;&gt;mission with software design (as we discuss in the introduction of solidbook)&lt;/a&gt; is fundamentally to implement these two high-level goals - one for users and the other for developers. If we&apos;re not doing both well, our software design attempts are failing.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ol&gt;
&lt;li&gt;[Users] Satisfy the needs of the user&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;[Developers] Do it in the most maintainable way possible&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first goal is accomplished by implementing the &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/feature-driven/#Features-are-the-only-essential-complexity&quot;&gt;essential complexity&lt;/a&gt;, that is - the &lt;em&gt;features&lt;/em&gt;. If it were possible to use a &lt;em&gt;no-code&lt;/em&gt; builder to reliably do this every time, then we&apos;d likely be doing that. However, that&apos;s not where we are as an industry, so we write code to realize systems that solve problems for people.&lt;/p&gt;
&lt;p&gt;The second goal exposes surface area for &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/feature-driven/#Accidental-complexity&quot;&gt;accidental complexity&lt;/a&gt;. We need to use paradigms, languages, and tools to build software. Some of these introduce inherent concepts that are known to cause (like state and sequence, according to Ben Moseley in his influential &quot;Out of the Tar Pit&quot; paper), and some of them introduce other subtle forms of complexity like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cognitive load&lt;/li&gt;
&lt;li&gt;Ripple&lt;/li&gt;
&lt;li&gt;Poor discoverability&lt;/li&gt;
&lt;li&gt;Poor understandability&lt;/li&gt;
&lt;li&gt;and &lt;a href=&quot;https://khalilstemmler.com/wiki/leaky-abstraction/&quot;&gt;leaky abstractions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&apos;s for this reason that I&apos;m starting to believe, more and more, that aligning with the &lt;em&gt;essence&lt;/em&gt; of the problem should be the school of thought to which we master software design. &lt;/p&gt;
&lt;p&gt;I believe that we should seek out &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/feature-driven/#A-collection-of-feature-first-techniques&quot;&gt;techniques&lt;/a&gt; that bring us &lt;em&gt;asympotically&lt;/em&gt; closer to implementing the bare minimum - the &lt;strong&gt;essential complexity&lt;/strong&gt; of the problem - and mitigates as much &lt;strong&gt;accidental complexity&lt;/strong&gt; as possible.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Why I Recommend a Feature-Driven Approach to Software Design]]></title><description><![CDATA[Introduction Here are a few pressing questions: What is the single-most important concept you can tell me about software design? How do you…]]></description><link>https://khalilstemmler.com/articles/software-design-architecture/feature-driven/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/software-design-architecture/feature-driven/</guid><pubDate>Fri, 23 Apr 2021 04:05:26 GMT</pubDate><content:encoded>&lt;h2 id=&quot;Introduction&quot; style=&quot;position:relative;&quot;&gt;Introduction&lt;a href=&quot;#Introduction&quot; aria-label=&quot;Introduction permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here are a few pressing questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What is the single-most important concept you can tell me about software design?&lt;/li&gt;
&lt;li&gt;How do you structure a (frontend or backend) so that it&apos;s testable, flexible, and maintainable?&lt;/li&gt;
&lt;li&gt;What am I supposed to test against in my tests? Classes? Methods? React components? How can I write tests that actually give me confidence in my code?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At first glance, these questions might appear to be a little bit unrelated. General software design advice, project structure, testing best practices. Hard to see the link, right?&lt;/p&gt;
&lt;p&gt;After having studied software design for a few years, the answer to each of these questions — and &lt;strong&gt;nearly all questions about how to write testable, flexible, and maintainable software&lt;/strong&gt;, is to &lt;strong&gt;focus on the features&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That is, I&apos;m telling you to be &lt;em&gt;feature-driven&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Features-are-the-only-essential-complexity&quot; style=&quot;position:relative;&quot;&gt;Features are the only essential complexity&lt;a href=&quot;#Features-are-the-only-essential-complexity&quot; aria-label=&quot;Features are the only essential complexity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For &quot;Part II — Humans &amp;#x26; Code&quot; of &lt;a href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt;, I had a chance to read &lt;em&gt;&lt;a href=&quot;http://curtclifton.net/papers/MoseleyMarks06a.pdf&quot;&gt;Out of the Tar Pit&lt;/a&gt;&lt;/em&gt; by Ben Moseley. &lt;/p&gt;
&lt;p&gt;In it, he discusses the ideas of &lt;strong&gt;essential complexity&lt;/strong&gt; and &lt;strong&gt;accidental complexity&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/features/scribble.png&quot; alt=&quot;Complexity&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Essential-complexity&quot; style=&quot;position:relative;&quot;&gt;Essential complexity&lt;a href=&quot;#Essential-complexity&quot; aria-label=&quot;Essential complexity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Software, in its simplest form, is a way to tame complexity in the world. We do this by developing &lt;em&gt;use cases&lt;/em&gt; (or features, you may call it) that cut through entropy and perform something useful for us.&lt;/p&gt;
&lt;p&gt;If my goal is to &quot;make friends in a new city&quot;, I can divide the application that helps me do that up into use cases/features. Three &lt;em&gt;features/use-cases&lt;/em&gt; may be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sign up&lt;/li&gt;
&lt;li&gt;Edit profile&lt;/li&gt;
&lt;li&gt;Get friend suggestions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The essential complexity involved in solving the problem of &quot;making friends in a new city&quot; is to &lt;em&gt;first&lt;/em&gt; identify all of the features - then, to merely implement them.&lt;/p&gt;
&lt;p&gt;Once all the features/use cases/&lt;a href=&quot;https://khalilstemmler.com/articles/client-side-architecture/principles/#Features-are-vertical-slices&quot;&gt;vertical slices&lt;/a&gt; are implemented, we&apos;re done.&lt;/p&gt;
&lt;h3 id=&quot;Accidental-complexity&quot; style=&quot;position:relative;&quot;&gt;Accidental complexity&lt;a href=&quot;#Accidental-complexity&quot; aria-label=&quot;Accidental complexity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;However, since we live in the real-world, we have to write code to accomplish this. &lt;/p&gt;
&lt;p&gt;And in most mainstream programming languages, the concepts of &lt;strong&gt;state&lt;/strong&gt; and &lt;strong&gt;sequence&lt;/strong&gt; exist.&lt;/p&gt;
&lt;p&gt;What&apos;s wrong with state and sequence? &lt;/p&gt;
&lt;p&gt;Well, according to Ben Moseley, &lt;strong&gt;state and sequence are the two leading causes of&lt;/strong&gt; &lt;strong&gt;accidental complexity&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;State — &quot;Have you tried turning it off and on again?&quot; Has anyone ever said that to you before? This is what happens when a system ends up in an &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/make-illegal-states-unrepresentable/&quot;&gt;illegal state&lt;/a&gt;. And maintaining state is hard. We have to keep track of variables, instances, etc.&lt;/li&gt;
&lt;li&gt;Sequence — &quot;First we do this, and then we need to do &lt;em&gt;this&lt;/em&gt;, but &lt;em&gt;only&lt;/em&gt; if &lt;em&gt;this&lt;/em&gt; happens&quot;. Most of us write in languages that support procedures and conditionals. When we have to ensure that things happen in a particular order, we&apos;re also introducing surface area for complexity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Accidental complexity is when the complexity we&apos;re faced with is not actually related to the complexity of the &lt;em&gt;problem&lt;/em&gt; (like the &lt;em&gt;essential&lt;/em&gt; ones — the features). Instead, &lt;strong&gt;accidental complexity is related to the &lt;em&gt;way&lt;/em&gt; we solve problems&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That means that languages or paradigms that contain state and sequence inadvertently introduce accidental complexity.&lt;/p&gt;
&lt;p&gt;Okay, can we write code without state and sequence?&lt;/p&gt;
&lt;p&gt;It turns out that we &lt;em&gt;can&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Mitigating-accidental-complexity-with-functional-programming&quot; style=&quot;position:relative;&quot;&gt;Mitigating accidental complexity with functional programming&lt;a href=&quot;#Mitigating-accidental-complexity-with-functional-programming&quot; aria-label=&quot;Mitigating accidental complexity with functional programming permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is where (purely) functional programming shines. &lt;a href=&quot;https://twitter.com/ScottWlaschin&quot;&gt;Scott Wlaschin&lt;/a&gt;&apos;s &lt;em&gt;Domain-Modeling Made Functional&lt;/em&gt; book depicts an approach to get as close to the essential complexity as possible by modelling &lt;em&gt;features/use cases&lt;/em&gt; (he calls them &lt;em&gt;workflows&lt;/em&gt;) using minimal-to-no state and sequence. &lt;/p&gt;
&lt;p&gt;For example, here&apos;s some pseudo-code for a &lt;em&gt;feature&lt;/em&gt; that can be modelled entirely using F#&apos;s algebraic type system.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/features/domain-modeling-functional.png&quot; alt=&quot;Functional Domain Modeling&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;From &quot;Domain Modeling Made Functional&quot; by Scott Wlaschin - highly recommended reading.&lt;/p&gt;
&lt;p&gt;This is a really thorough approach. I think it&apos;s amazing. But real pure-&lt;em&gt;ish&lt;/em&gt; functional programming isn&apos;t for the faint of heart. This is some seriously disciplined programming. By modeling the entire domain from scratch, similar to the way we build up math equations from first principles, this is &lt;em&gt;truly&lt;/em&gt; the way that we &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/make-illegal-states-unrepresentable/&quot;&gt;make illegal states unrepresentable&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;However, most of us want a &lt;em&gt;little bit&lt;/em&gt; of state and sequence. Modelling purely functional features like this can be challenging. For many, composing software this way is an entirely different way to think about programming. Even RxJs can be challenging.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;&quot;&gt;https://patrickroza.com/blog/result-composition-and-error-handling/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/features/roza.jpg&quot; alt=&quot;Patrick Roza&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;See Patrick Roza&apos;s &lt;a target=&quot;_blank&quot; href=&quot;https://patrickroza.com/blog/result-composition-and-error-handling/&quot;&gt;Result Composition and Error Handling techniques in TypeScript&lt;/a&gt;. I currently think that pure functional programming in TypeScript sits further on the structural side than it does on the developer experience side.&lt;/p&gt;
&lt;h3 id=&quot;Structure-vs-developer-experience--FP-is-hard&quot; style=&quot;position:relative;&quot;&gt;Structure vs. developer experience — FP is hard&lt;a href=&quot;#Structure-vs-developer-experience--FP-is-hard&quot; aria-label=&quot;Structure vs developer experience  FP is hard permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Like most things in design, there&apos;s a push-pull between priorities. &lt;/p&gt;
&lt;p&gt;In software design, I call it the balance between &lt;em&gt;Structure&lt;/em&gt; and &lt;em&gt;Developer Experience&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;You want a structured approach to doing things, but you don&apos;t want it to hinder your productivity.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/features/structure-vs-experience.jpg&quot; alt=&quot;Use%20a%20Feature-Driven%20Approach%20to%20Software%20Design%207e6e084055f8468cb3d9d8db19cbd148/Ezbg2UJX0AIfpBA.jpg&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Structure vs. Developer Experience - from &lt;a href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/features/balancing-structure-developer-experience.jpg&quot; alt=&quot;Use%20a%20Feature-Driven%20Approach%20to%20Software%20Design%207e6e084055f8468cb3d9d8db19cbd148/EzbhnOKXEAET_GB.jpg&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Balancing structure vs. developer experience - from &lt;a href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Therefore, the majority of the web development industry codes in paradigms and with languages that deal with state and sequence (TypeScript, JavaScript, Python, etc). &lt;/p&gt;
&lt;p&gt;Well, that&apos;s certainly some accidental complexity that we&apos;re taking on isn&apos;t it? Yes... and it&apos;s fine. &lt;/p&gt;
&lt;p&gt;But that doesn&apos;t mean we don&apos;t need to keep tabs on it.&lt;/p&gt;
&lt;p&gt;Luckily for us, OOP folks from the 90s discovered a great feature-first way to consistently, reliably, and confidently write code containing state and sequence.&lt;/p&gt;
&lt;p&gt;It&apos;s called &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/introduction-to-tdd/&quot;&gt;TDD&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Use-feature-first-TDD-to-tame-state-and-sequence-complexity&quot; style=&quot;position:relative;&quot;&gt;Use feature-first TDD to tame (state and sequence) complexity&lt;a href=&quot;#Use-feature-first-TDD-to-tame-state-and-sequence-complexity&quot; aria-label=&quot;Use feature first TDD to tame state and sequence complexity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There&apos;s more to Test-Driven Development than just unit testing React components and classes.&lt;/p&gt;
&lt;p&gt;The best ROI comes through figuring out a way to continue to add and change code, and ensure that the &lt;em&gt;features&lt;/em&gt; of our application still work. This is where the majority of our efforts should lie — because the features are the essential complexity, after all. &lt;/p&gt;
&lt;p&gt;The &quot;feature-first way&quot; to do TDD is to do &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/introduction-to-tdd/#Double-Loop-TDD&quot;&gt;Double Loop TDD&lt;/a&gt;. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Outer loop&lt;/strong&gt;: Write the acceptance test (which can be written as an &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/introduction-to-tdd/#Types-of-tests-unit-integration-E2E-acceptance&quot;&gt;integration or end-to-end test&lt;/a&gt;); this is the essential complexity written in English.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inner loop&lt;/strong&gt; : Red-Green-Refactor your components, classes, etc until the outer loop passes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/features/double-loop-tdd.png&quot; alt=&quot;Double Loop TDD&quot;&gt;&lt;/p&gt;
&lt;p&gt;This isn&apos;t a new thing, I just think that we&apos;re all struggling to agree on the terminology and recognize that we&apos;re all talking about the same things (&lt;a href=&quot;https://kentcdodds.com/blog/write-tests/&quot;&gt;see this blog post from the Dodds&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&quot;A-collection-of-feature-first-techniques&quot; style=&quot;position:relative;&quot;&gt;A collection of feature-first techniques&lt;a href=&quot;#A-collection-of-feature-first-techniques&quot; aria-label=&quot;A collection of feature first techniques permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Some of the best techniques I&apos;ve found that help us align with the essence of the problem at hand and cut out the noise (tech stack, language, paradigm, etc) are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/graphql/ddd/schema-design/#Event-Storming&quot;&gt;Event Storming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://eventmodeling.org/posts/what-is-event-modeling/&quot;&gt;Event Modeling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;Use-Case Driven Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Acceptance Test-Driven Development (also called Double Loop TDD)&lt;/li&gt;
&lt;li&gt;... way more, to be continued&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Benefits-of-a-feature-first-approach&quot; style=&quot;position:relative;&quot;&gt;Benefits of a feature-first approach&lt;a href=&quot;#Benefits-of-a-feature-first-approach&quot; aria-label=&quot;Benefits of a feature first approach permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We get a lot of benefits when we apply a &quot;feature-first&quot; approach. &lt;/p&gt;
&lt;h3 id=&quot;Project-structure&quot; style=&quot;position:relative;&quot;&gt;Project structure&lt;a href=&quot;#Project-structure&quot; aria-label=&quot;Project structure permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;At the folder-level:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;More cohesive feature folders&lt;/li&gt;
&lt;li&gt;More discoverable folder structures&lt;/li&gt;
&lt;li&gt;Less &quot;cognitive load&quot; flipping around files/folders&lt;/li&gt;
&lt;li&gt;Screaming architecture (easy to remember what the system does)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Overall-system-simplicity&quot; style=&quot;position:relative;&quot;&gt;Overall system simplicity&lt;a href=&quot;#Overall-system-simplicity&quot; aria-label=&quot;Overall system simplicity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;At the system level:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Consistent testing strategy with a high ROI (acceptance test for each feature)&lt;/li&gt;
&lt;li&gt;Simpler architecture&lt;/li&gt;
&lt;li&gt;Easy to keep tabs on coupling between features/vertical slices (SRP)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/features/vertical-slices.png&quot; alt=&quot;Vertical slices&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Software-craftsmanship&quot; style=&quot;position:relative;&quot;&gt;Software craftsmanship&lt;a href=&quot;#Software-craftsmanship&quot; aria-label=&quot;Software craftsmanship permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;At the professional level&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Decouple large projects into sets of features&lt;/li&gt;
&lt;li&gt;Provide better estimates&lt;/li&gt;
&lt;li&gt;Understand where new technologies fit into a vertical slice (feature)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;DDDForum-GitHub-Repo&quot; style=&quot;position:relative;&quot;&gt;DDDForum (GitHub Repo)&lt;a href=&quot;#DDDForum-GitHub-Repo&quot; aria-label=&quot;DDDForum GitHub Repo permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can work in a feature-driven way on both front-end and back-end architectures. Take a look &lt;a href=&quot;https://github.com/stemmlerjs/ddd-forum/&quot;&gt;at the code for DDDForum&lt;/a&gt;, the app we build in &lt;a href=&quot;http://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The backend follows a feature-first project structure, organized by &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/features/ddd-forum.png&quot; alt=&quot;DDDForum project structure&quot;&gt;&lt;/p&gt;
&lt;p&gt;The frontend application is currently being refactored to follow a feature-first approach for the next iterations of the &lt;a href=&quot;https://khalilstemmler.com/articles/client-side-architecture/introduction/&quot;&gt;Client-Side Architecture Basics guide&lt;/a&gt;. In the next iterations, you&apos;ll learn:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to craft a feature-first project architecture&lt;/li&gt;
&lt;li&gt;How to consistently evolve code using TDD &amp;#x26; Unit, Integration, and E2E tests regardless of your stack&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Part-II--Humans--code-from-solidbookio&quot; style=&quot;position:relative;&quot;&gt;Part II — Humans &amp;#x26; code from &lt;a href=&quot;http://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt;&lt;a href=&quot;#Part-II--Humans--code-from-solidbookio&quot; aria-label=&quot;Part II  Humans  code from solidbookio permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&apos;ll be writing more content about this phenomenon on the blog, but if you&apos;re looking for an in-depth discussion on how to design human-friendly codebases, the Humans &amp;#x26; Code part of solidbook.io just went out last week. We learn how to structure repos, organize things, name them, handle errors (and more) — all in a feature-first way. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/features/EzbYtjuX0AA3YSu.jpg&quot; alt=&quot;Use%20a%20Feature-Driven%20Approach%20to%20Software%20Design%207e6e084055f8468cb3d9d8db19cbd148/EzbYtjuX0AA3YSu.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/features/EzbYvBXWQAEqPUL.jpg&quot; alt=&quot;Use%20a%20Feature-Driven%20Approach%20to%20Software%20Design%207e6e084055f8468cb3d9d8db19cbd148/EzbYvBXWQAEqPUL.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/features/EzbYwH4XIAM2jo0.jpg&quot; alt=&quot;Use%20a%20Feature-Driven%20Approach%20to%20Software%20Design%207e6e084055f8468cb3d9d8db19cbd148/EzbYwH4XIAM2jo0.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/features/EzbYws_WUAUb6q4.jpg&quot; alt=&quot;Use%20a%20Feature-Driven%20Approach%20to%20Software%20Design%207e6e084055f8468cb3d9d8db19cbd148/EzbYws_WUAUb6q4.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;Check it out &lt;a href=&quot;https://wiki.solidbook.io/Part-II-Humans-&amp;#x26;-Code-dd6967bd89db4ad9bf505f12fc7289b4&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Introduction to Test-Driven Development (TDD) with Classic TDD Example]]></title><description><![CDATA[Watch on YouTube If you're like me, you see programming as a type of trade .  Over the past year, I've been paying more attention to how…]]></description><link>https://khalilstemmler.com/articles/test-driven-development/introduction-to-tdd/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/test-driven-development/introduction-to-tdd/</guid><pubDate>Wed, 31 Mar 2021 15:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;special-quote&quot;&gt;🌱  This article hasn&apos;t fully bloomed. It&apos;s very likely to change over the next little while.&lt;/p&gt;
&lt;h2 id=&quot;Watch-on-YouTube&quot; style=&quot;position:relative;&quot;&gt;Watch on YouTube&lt;a href=&quot;#Watch-on-YouTube&quot; aria-label=&quot;Watch on YouTube permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;428px&quot; src=&quot;https://www.youtube.com/embed/a1jdwlujdk0&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;!-- `youtube:https://www.youtube.com/embed/a1jdwlujdk0`
[https://youtu.be/](https://youtu.be/a1jdwlujdk0) --&gt;
&lt;p&gt;If you&apos;re like me, you see programming as a type of &lt;em&gt;trade &lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Over the past year, I&apos;ve been paying more attention to how traditional tradespeople work. I&apos;ve been looking for parallels between how &lt;em&gt;they&lt;/em&gt; work and how &lt;em&gt;we&lt;/em&gt; work as software developers. &lt;/p&gt;
&lt;p&gt;When I most recently took my car in to get an oil change, I noticed that the technicians seemed to &lt;strong&gt;consistently, reliably, and confidently get the job done, and get it done right&lt;/strong&gt;. One client after the next. They weren&apos;t making messes. They weren&apos;t missing their estimates. They weren&apos;t discovering that things won&apos;t work at the last minute - in fact, I&apos;ve even seen them come out, 2 minutes into the job to let someone know that there&apos;s more work to be done than they initially expected.&lt;/p&gt;
&lt;p&gt;It appears, at least to me, as if these are principled workers, and — forgive the pun, but it seems like &lt;em&gt;they&apos;re not&lt;/em&gt; &lt;em&gt;reinventing the wheel&lt;/em&gt;. &lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Part of what it means to be an &lt;em&gt;Agile&lt;/em&gt; software craftsperson is to &lt;strong&gt;consistently deliver value to the customer&lt;/strong&gt;. That&apos;s hard. But that&apos;s what we&apos;re constantly trying to do here.&lt;/p&gt;
&lt;p&gt;The goal of this blog is to discover the best techniques for writing testable, flexible, maintainable code, and to teach others how to do it too. Today, the software quality attribute we&apos;re most interested in is &lt;em&gt;testability&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;And in my experience:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The best way to write testable code &lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; is to write the test first&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;Introduction&quot; style=&quot;position:relative;&quot;&gt;Introduction&lt;a href=&quot;#Introduction&quot; aria-label=&quot;Introduction permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is the first post in a series on &lt;strong&gt;Test-Driven Development (TDD)&lt;/strong&gt;: a &lt;em&gt;test-first&lt;/em&gt; technique for developing software 🧪.&lt;/p&gt;
&lt;p&gt;In this introductory post, you&apos;ll build a beginner foundation for TDD. We&apos;ll learn about what TDD &lt;em&gt;is,&lt;/em&gt; what makes it important, and &lt;strong&gt;how developers are using it to consistently deliver value on real-life projects&lt;/strong&gt;. We&apos;ll also discuss what makes testing so challenging to get right, and in the end, we&apos;ll wrap up with a demonstration of the &lt;em&gt;Classic TDD&lt;/em&gt; process, using TDD to construct a palindrome checker.&lt;/p&gt;
&lt;p&gt;You&apos;ll learn everything you need to know to get started practicing the &lt;em&gt;TDD Red-Green-Refactor&lt;/em&gt; process. This is just the starting point. We need to get this foundation down first before we can learn how to apply advanced TDD techniques in the real-world &lt;sup id=&quot;fnref-3&quot;&gt;&lt;a href=&quot;#fn-3&quot; class=&quot;footnote-ref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. &lt;/p&gt;
&lt;p&gt;Let&apos;s begin.&lt;/p&gt;
&lt;h2 id=&quot;Why-tests&quot; style=&quot;position:relative;&quot;&gt;Why tests?&lt;a href=&quot;#Why-tests&quot; aria-label=&quot;Why tests permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are lots of reasons why tests are helpful, but the two best reasons, in my opinion, are &lt;strong&gt;confidence&lt;/strong&gt; and &lt;strong&gt;feedback&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Confidence----&quot; style=&quot;position:relative;&quot;&gt;Confidence ⭐ ⭐ ⭐ ⭐&lt;a href=&quot;#Confidence----&quot; aria-label=&quot;Confidence     permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;They say that &lt;strong&gt;change is a constant in software development&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;To find the &lt;em&gt;confidence&lt;/em&gt; to safely add, remove, or refactor code without the fear of introducing bugs and regressions, we need tests. &lt;/p&gt;
&lt;p&gt;This is especially important later on in a project when the codebase is much larger than it was at the beginning, and there&apos;s way more code that one human being can mentally account for anymore. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/intro/progress-with-tests.svg&quot; alt=&quot;How TDD progresses with and without tests&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;How projects with good tests, bad tests, and no tests progress over time. Without tests (or with bad tests), it&apos;s hard to continue to safely make progress because new changes introduce regressions. Refactoring without tests is a great way to introduce regressions.&lt;/p&gt;
&lt;p&gt;I can tell you from experience that this is not a fun situation to be in— thousands of lines of code into a project with no tests and no safety. It&apos;s a great way to turn a promising codebase into an unstable mess.&lt;/p&gt;
&lt;h3 id=&quot;Feedback-----&quot; style=&quot;position:relative;&quot;&gt;Feedback ⭐ ⭐ ⭐ ⭐ ⭐&lt;a href=&quot;#Feedback-----&quot; aria-label=&quot;Feedback      permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In my opinion, the most important reason for tests is &lt;em&gt;feedback&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Tests give us &lt;em&gt;feedback&lt;/em&gt; to let us know:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When regressions have been introduced&lt;/li&gt;
&lt;li&gt;What our progress towards implementing a feature looks like&lt;/li&gt;
&lt;li&gt;That we &lt;em&gt;actually&lt;/em&gt; understand the customer requirements&lt;/li&gt;
&lt;li&gt;And if our designs are feasible&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Depending on how you think about it, &lt;em&gt;confidence&lt;/em&gt; may actually come from the &lt;em&gt;feedback&lt;/em&gt; we get from tests.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/intro/feedback.png&quot; alt=&quot;Introduction%20to%20Test-Driven%20Development%20(TDD)%20with%2022bd00e6d7044c10a96fb92c4bcc8816/testing_fundamentals_(53).png&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;[Principle]: Listen to your tests —&lt;/b&gt; Tests that are hard to write typically signal a deficiency in design. Use the immediate feedback you get from feeling out &lt;i&gt;how hard&lt;/i&gt; it is to write a particular test to reconsider the design.&lt;/p&gt;
&lt;p&gt;Feedback is so important that &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Kent_Beck&quot;&gt;Kent Beck&lt;/a&gt; lists it as one of the &lt;strong&gt;primary values&lt;/strong&gt; of &lt;a target=&quot;_blank&quot; href=&quot;https://www.amazon.ca/Extreme-Programming-Explained-Embrace-Change/dp/0321278658&quot;&gt;Extreme Programming&lt;/a&gt;: the influential Agile software development methodology.&lt;/p&gt;
&lt;h3 id=&quot;More-reasons-to-write-tests&quot; style=&quot;position:relative;&quot;&gt;More reasons to write tests&lt;a href=&quot;#More-reasons-to-write-tests&quot; aria-label=&quot;More reasons to write tests permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Measure progress&lt;/strong&gt; ⭐ ⭐&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sculpt out public APIs&lt;/strong&gt; ⭐&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Understand requirements&lt;/strong&gt; ⭐ ⭐&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep a feature in scope&lt;/strong&gt; ⭐ ⭐&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documentation for other developers&lt;/strong&gt; ⭐ ⭐ ⭐&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Why-testing-is-hard&quot; style=&quot;position:relative;&quot;&gt;Why testing is hard&lt;a href=&quot;#Why-testing-is-hard&quot; aria-label=&quot;Why testing is hard permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I didn&apos;t start writing tests until later in my career. When I first started out, I knew that we should probably have them, but as for writing them? Yeah, right. Like many new developers, I was lost as to how to even get started. After surveying the landscape, here&apos;s why I think testing is hard.&lt;/p&gt;
&lt;h3 id=&quot;Testing-isnt-regularly-taught-in-schools&quot; style=&quot;position:relative;&quot;&gt;Testing isn&apos;t regularly taught in schools&lt;a href=&quot;#Testing-isnt-regularly-taught-in-schools&quot; aria-label=&quot;Testing isnt regularly taught in schools permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This may not be the case for some readers, but the majority of my college/university/bootcamp-going peers weren&apos;t exposed to how to properly test code until &lt;strong&gt;a mentor sat down and showed them how to do it&lt;/strong&gt;. &lt;/p&gt;
&lt;h3 id=&quot;As-an-industry-we-struggle-to-agree-on-testing-terminology&quot; style=&quot;position:relative;&quot;&gt;As an industry, we struggle to agree on testing terminology&lt;a href=&quot;#As-an-industry-we-struggle-to-agree-on-testing-terminology&quot; aria-label=&quot;As an industry we struggle to agree on testing terminology permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Ask two developers what they believe an &lt;em&gt;integration test&lt;/em&gt; is. &lt;a target=&quot;_blank&quot; href=&quot;https://martinfowler.com/bliki/IntegrationTest.html&quot;&gt;As Fowler writes&lt;/a&gt;, there are two completely different notions of what this means, and we still haven&apos;t converged on a standard. &lt;/p&gt;
&lt;p&gt;This is true for much of the other test types as well (unit, acceptance, E2E, contract, etc).&lt;/p&gt;
&lt;p&gt;It also appears that your organization style and role (front-end, back-end, full-stack) &lt;a target=&quot;_blank&quot; href=&quot;https://twitter.com/khalilstemmler/status/1371466021580767238&quot;&gt;play a role in how we see certain types of tests as well&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Understanding-what-to-test-and-how-to-test-it-takes-practice&quot; style=&quot;position:relative;&quot;&gt;Understanding &lt;em&gt;what to test&lt;/em&gt; and &lt;em&gt;how to test it&lt;/em&gt; takes practice&lt;a href=&quot;#Understanding-what-to-test-and-how-to-test-it-takes-practice&quot; aria-label=&quot;Understanding what to test and how to test it takes practice permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Knowing &lt;strong&gt;what to test&lt;/strong&gt; is hard. And this is especially misleading for newer developers since a lot of &lt;strong&gt;libraries and frameworks tell you how to test code within their &lt;em&gt;library or framework&lt;/em&gt;,&lt;/strong&gt; but don&apos;t actually give you best practices for testing &lt;em&gt;your&lt;/em&gt; code within them.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/intro/what-and-how-to-test-tdd.png&quot; alt=&quot;what-and-how-to-test-tdd&quot;&gt;&lt;/p&gt;
&lt;p&gt;The magic rule here is to test against &lt;em&gt;behavior&lt;/em&gt;. And if you understand the requirements, we can pretty much turn those user stories or customer requirements &lt;em&gt;directly&lt;/em&gt; into tests.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;[Principle]: Prefer tests against behavior, not implementation&lt;/b&gt; — Seek to test &quot;behavior&quot; using the &lt;a href=&quot;https://khalilstemmler.com/articles/domain-driven-design-intro/&quot;&gt;language of the domain&lt;/a&gt; to write the tests. There will be times when the tests you need to write are actually against more technical concepts (ie: integration tests), but you can always write your tests to test behavior, not implementation.&lt;/p&gt; 
&lt;p&gt;As for &lt;strong&gt;knowing &lt;em&gt;how&lt;/em&gt; to test&lt;/strong&gt; behavior— that&apos;s a different story. &lt;/p&gt;
&lt;p&gt;Most of the time, the code we write is more complex than plain ol&apos; vanilla JavaScript or TypeScript. Typically, we&apos;re writing code that relies on dependencies like web servers, caches, databases, and even front-end library code like React or Vue.js &lt;sup id=&quot;fnref-3&quot;&gt;&lt;a href=&quot;#fn-3&quot; class=&quot;footnote-ref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;It takes some up-front planning and foresight to figure out how we&apos;re going to test our code in most of these scenarios. &lt;/p&gt;
&lt;h3 id=&quot;We-leave-testing-until-the-very-end&quot; style=&quot;position:relative;&quot;&gt;We leave testing until the very end&lt;a href=&quot;#We-leave-testing-until-the-very-end&quot; aria-label=&quot;We leave testing until the very end permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I also think that testing is hard because developers often write tests &lt;em&gt;after&lt;/em&gt; the production code has been written. While this approach sometimes works, I don&apos;t think it&apos;s the best way to go about things. &lt;/p&gt;
&lt;p&gt;Writing all the tests at the end &lt;em&gt;isn&apos;t really&lt;/em&gt; acting like we value &lt;strong&gt;feedback&lt;/strong&gt;, because we&apos;re leaving all the uncertainty of &quot;if we can even test this thing&quot;, &quot;if this thing was designed well&quot;, and &quot;if this thing even works&quot; to the very end.&lt;/p&gt;
&lt;h3 id=&quot;Testing-is-a-part-of-architecture&quot; style=&quot;position:relative;&quot;&gt;Testing is a part of architecture&lt;a href=&quot;#Testing-is-a-part-of-architecture&quot; aria-label=&quot;Testing is a part of architecture permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This has been a massive realization for me. And I hope it will be for you as well. &lt;strong&gt;Testing is a part of architecture&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Ralph Johnson, co-author of the &lt;a target=&quot;_blank&quot; href=&quot;https://www.amazon.ca/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612&quot;&gt;famous design patterns book&lt;/a&gt; said this of &lt;em&gt;architecture&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;... it is the decisions you wish you could get right early in a project”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Architecture is about the expensive, hard to change stuff like choosing a tech stack (React, Apollo, GraphQL, Mongo), an architectural style (Reactive, Event-Driven, Transaction Script), or in this case — our testing approach.&lt;/p&gt;
&lt;p&gt;The trouble with &lt;em&gt;not&lt;/em&gt; thinking about how we&apos;re going to &lt;strong&gt;test&lt;/strong&gt; early on is that we&apos;re leaving a &lt;em&gt;lot of room&lt;/em&gt; for uncertainty down the road towards the end of the project. &lt;/p&gt;
&lt;p&gt;We&apos;re not sure if there are edge cases we&apos;re missing, if there are structural problems with the way we&apos;ve written our code, and if we&apos;re even going to be able to test the thing.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/intro/stress-level-tdd-test-driven-development.svg&quot; alt=&quot;Stress level with tdd&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Your stress level over time when you realize code is hard to deploy and test towards the end of the project.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;[Principle]: Expose uncertainty early&lt;/b&gt; - Decide on how you&apos;re going to test and deploy your application at the start of the project. Get your test architecture set up in Sprint 0.&lt;/p&gt;
&lt;p&gt;As &lt;em&gt;Agile&lt;/em&gt; software developers, we should value &lt;strong&gt;feedback,&lt;/strong&gt; exposing &lt;em&gt;bad design&lt;/em&gt; and &lt;em&gt;uncertainty&lt;/em&gt; as early as possible.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;I&apos;m not a great programmer, I&apos;m just a good programmer with great habits&quot; — Kent Beck, the creator of &lt;a href=&quot;https://en.wikipedia.org/wiki/Extreme_programming&quot;&gt;Extreme Programming&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;At this point, I hope you&apos;re sold on what tests can do for us and why we&apos;d want them.&lt;/p&gt;
&lt;p&gt;Now let&apos;s talk about the TDD process.&lt;/p&gt;
&lt;h2 id=&quot;The-Test-Driven-Development-TDD-Process&quot; style=&quot;position:relative;&quot;&gt;The Test-Driven Development (TDD) Process&lt;a href=&quot;#The-Test-Driven-Development-TDD-Process&quot; aria-label=&quot;The Test Driven Development TDD Process permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;TDD (test-driven development), is a technique — or a &lt;em&gt;process&lt;/em&gt; for developing software. The goal is to keep code quality high and keep you productive, even as projects grow to be really large and complex. &lt;/p&gt;
&lt;h3 id=&quot;Red-Green-Refactor&quot; style=&quot;position:relative;&quot;&gt;Red-Green-Refactor&lt;a href=&quot;#Red-Green-Refactor&quot; aria-label=&quot;Red Green Refactor permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The TDD process works by following the &lt;em&gt;Red-Green-Refactor&lt;/em&gt; loop. It goes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Red&lt;/strong&gt; — Write a failing test&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Green&lt;/strong&gt; — Write just enough code that will pass the failing test&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Refactor&lt;/strong&gt; — Criticize the design and refactor the code, keeping the tests intact&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/intro/red-green-refactor-tdd-test-driven-development.svg&quot; alt=&quot;Red-Green-Refactor TDD&quot;&gt;&lt;/p&gt;
&lt;p&gt;We should like this process because it &lt;strong&gt;keeps tight feedback loops&lt;/strong&gt;. It gives us the ability to produce cleaner, simpler designs and helps us introduce abstractions only when they are absolutely necessary (see &lt;a href=&quot;https://khalilstemmler.com/wiki/yagni/&quot;&gt;YAGNI&lt;/a&gt; — You Aren&apos;t Gonna Need It).&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Should I always follow the TDD loop?&lt;/b&gt;: I know what you&apos;re thinking. Khalil, you can&apos;t expect me to completely follow this rule. &lt;i&gt;You&lt;/i&gt; probably don&apos;t even do this. You&apos;re right. I don&apos;t always follow it. Rules are a great way to get started, but sometimes I break them. When I&apos;m driving, I&apos;ll sometimes perform a rolling stop instead of coming to a complete stop. When I&apos;m crossing the street, sometimes I&apos;ll take a quick gander to my left and right before jaywalking. I&apos;m of the mindset that if you master this technique, you&apos;ll have the skill to decide when to break it, and to do so with confidence.&lt;/p&gt;
&lt;h3 id=&quot;Types-of-tests-unit-integration-E2E-acceptance&quot; style=&quot;position:relative;&quot;&gt;Types of tests (unit, integration, E2E, acceptance)&lt;a href=&quot;#Types-of-tests-unit-integration-E2E-acceptance&quot; aria-label=&quot;Types of tests unit integration E2E acceptance permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There are different types of tests, and &lt;strong&gt;you can apply the Red-Green-Refactor &lt;em&gt;process&lt;/em&gt; to each of them&lt;/strong&gt;. As we mentioned earlier, the scopes of these tests are up for interpretation, and they may be slightly different if you&apos;re a front-end or back-end developer, but in general, they are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unit ⭐  — Test an individual, isolated component&lt;/li&gt;
&lt;li&gt;Integration ⭐ ⭐ ⭐ ⭐  — Test that multiple units work together OR &quot;tests that confirm our code works against code we don&apos;t own&quot; (like external APIs, databases, caches, etc)&lt;/li&gt;
&lt;li&gt;End-to-End ⭐ ⭐   — Tests that act as a user &lt;em&gt;actually using the application;&lt;/em&gt; tests the entire stack from top-to-bottom&lt;/li&gt;
&lt;li&gt;Acceptance ⭐ ⭐ ⭐ ⭐ ⭐  — &lt;a href=&quot;https://khalilstemmler.com/articles/domain-driven-design-intro/&quot;&gt;Domain-driven&lt;/a&gt; tests that verify a user story (also comparable to a &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use case&lt;/a&gt;, customer test, &lt;a href=&quot;https://khalilstemmler.com/articles/oop-design-principles/command-query-separation/&quot;&gt;command/query&lt;/a&gt;, feature, or vertical slice) works as expected.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;The-big-picture-How-TDD-works-on-real-life-projects&quot; style=&quot;position:relative;&quot;&gt;The big picture: How TDD works on real-life projects&lt;a href=&quot;#The-big-picture-How-TDD-works-on-real-life-projects&quot; aria-label=&quot;The big picture How TDD works on real life projects permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Allow me to give you the big-picture so you can see where we&apos;re going with TDD and &lt;strong&gt;why I find it so incredibly powerful&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In the real-world, a good testing architecture typically involves more than one type of test.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/intro/tdd-in-extreme-programming.png&quot; alt=&quot;tdd-in-extreme-programming&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;In Extreme Programming, tests are a mandatory part of planning and feedback loops.&lt;/p&gt;
&lt;p&gt;As written about in the influential &quot;&lt;a target=&quot;_blank&quot; href=&quot;https://www.amazon.ca/Extreme-Programming-Explained-Embrace-Change/dp/0321278658&quot;&gt;Extreme Programming Explained&lt;/a&gt;&quot; and &quot;&lt;a target=&quot;_blank&quot; href=&quot;https://www.amazon.com/dp/0321503627&quot;&gt;Growing Object-Oriented Software Guided By Tests&lt;/a&gt;&quot; books, the test we start with is the &lt;strong&gt;acceptance test&lt;/strong&gt;: that is — the test that most closely represents the feature we want to build. From here, we build out the internals of the feature using other tests including &lt;strong&gt;unit tests&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Starting-with-the-acceptance-test&quot; style=&quot;position:relative;&quot;&gt;Starting with the acceptance test&lt;a href=&quot;#Starting-with-the-acceptance-test&quot; aria-label=&quot;Starting with the acceptance test permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Starting with the acceptance test, we convert the user story into a &lt;em&gt;behavioral test&lt;/em&gt; written using the exact same language from the domain. This means our tests should read like plain English, and represents the exact user story that we&apos;re about to build.&lt;/p&gt;
&lt;img style=&quot;width: 100%;&quot; src=&quot;/img/blog/tdd/intro/tdd-start-with-acceptance-test.svg&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;Acceptance tests read like domain-driven customer requirements. These are the user stories, commands/queries, use cases, and so on.&lt;/p&gt;
&lt;p&gt;From here, we identify the objects and their public APIs (properties, methods, etc) for the feature we need to realize while &lt;a href=&quot;https://khalilstemmler.com/articles/oop-design-principles/maintain-a-single-layer-of-abstraction/&quot;&gt;maintaining a single layer of abstraction&lt;/a&gt;. When we need to, we step a layer deeper into the objects we come up with and write more specific tests. &lt;/p&gt;
&lt;p&gt;This technique is called &lt;em&gt;Double Loop TDD&lt;/em&gt; and it&apos;s how we &lt;em&gt;sculpt&lt;/em&gt; our solution to fit our tests.&lt;/p&gt;
&lt;h3 id=&quot;Double-Loop-TDD&quot; style=&quot;position:relative;&quot;&gt;Double Loop TDD&lt;a href=&quot;#Double-Loop-TDD&quot; aria-label=&quot;Double Loop TDD permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The idea of Double Loop TDD is to maintain &lt;strong&gt;two TDD loops&lt;/strong&gt;.&lt;/p&gt;
&lt;img style=&quot;width: 100%;&quot; src=&quot;/img/blog/tdd/intro/double-loop-tdd.svg&quot;/&gt;
&lt;p&gt;The &lt;strong&gt;outer loop&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;is the &lt;strong&gt;acceptance test&lt;/strong&gt; loop&lt;/li&gt;
&lt;li&gt;and it &lt;strong&gt;catches regressions&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;strong&gt;inner loop&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;is the &lt;strong&gt;unit test&lt;/strong&gt; loop&lt;/li&gt;
&lt;li&gt;and it &lt;strong&gt;measures progress&lt;/strong&gt; towards implementing a feature&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When we&apos;re writing tests for the &lt;em&gt;outside&lt;/em&gt; acceptance test loop, we&apos;re usually coding from the &lt;strong&gt;outside-in&lt;/strong&gt;. When we&apos;re writing tests for the &lt;em&gt;inner&lt;/em&gt; unit test loop, we&apos;re coding &lt;strong&gt;inside-out&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Inside-Out and Outside-In. These are also names for two schools of thought for TDD. &lt;/p&gt;
&lt;h3 id=&quot;Classic-Inside-OutChicago-and-Mockist-Outside-InLondon-TDD&quot; style=&quot;position:relative;&quot;&gt;Classic (Inside-Out/Chicago) and Mockist (Outside-In/London) TDD&lt;a href=&quot;#Classic-Inside-OutChicago-and-Mockist-Outside-InLondon-TDD&quot; aria-label=&quot;Classic Inside OutChicago and Mockist Outside InLondon TDD permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Classic TDD (also known as &lt;em&gt;Inside Out&lt;/em&gt; or &lt;em&gt;Chicago style TDD&lt;/em&gt;) is a style of &lt;strong&gt;unit testing&lt;/strong&gt; where we start from the unit tests, and build &lt;em&gt;outwards,&lt;/em&gt; fleshing out the internal details of the objects we know we need. This is probably the most straightforward and commonly known form of TDD.&lt;/p&gt;
&lt;p&gt;Whereas with Mockist TDD (also known as &lt;em&gt;Outside In&lt;/em&gt; or &lt;em&gt;London style TDD&lt;/em&gt;), we start at the boundaries of the application (typically the controller) and end up coding &lt;em&gt;inwards&lt;/em&gt;, creating &lt;em&gt;mock objects&lt;/em&gt; to build out the shape of the system and the APIs of objects we know we&apos;re going to need to &lt;strong&gt;fulfill the acceptance test&lt;/strong&gt;.&lt;/p&gt;
&lt;img style=&quot;width: 100%;&quot; src=&quot;/img/blog/tdd/intro/outside-in-inside-out-tdd.svg&quot;/&gt;
&lt;p&gt;Both styles of TDD are useful. By using a mixture of both inside-out and outside-in, we can compose an elegant approach to TDD our way through an entire project.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;[Principle]: Inside-Out when you know how to build it, and Outside-In when you&apos;re working out the pieces.&lt;/p&gt; 
&lt;hr&gt;
&lt;p&gt;We&apos;ve covered about 70% of the essential theory for TDD so far. If your head is spinning, that&apos;s OK. One of the goals in this introduction is to show you the big picture of TDD and how it&apos;s used to develop software from start to finish.&lt;/p&gt;
&lt;p&gt;Next, you&apos;ll want to get the technique down. &lt;/p&gt;
&lt;p&gt;Let&apos;s walk through a demonstration. &lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Reminder&lt;/b&gt;: If you prefer to see the demonstration &lt;i&gt;visually&lt;/i&gt;, you can &lt;a target=&quot;_blank&quot; href=&quot;https://www.youtube.com/watch?v=a1jdwlujdk0&amp;t=230s&amp;ab_channel=KhalilStemmler&quot;&gt;watch me code it here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Demonstration-Classic-TDD--Palindrome-Example&quot; style=&quot;position:relative;&quot;&gt;Demonstration: Classic TDD — Palindrome Example&lt;a href=&quot;#Demonstration-Classic-TDD--Palindrome-Example&quot; aria-label=&quot;Demonstration Classic TDD  Palindrome Example permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&apos;ll build a palindrome checker using the &lt;em&gt;Classic TDD&lt;/em&gt; approach.&lt;/p&gt;
&lt;h3 id=&quot;Requirements&quot; style=&quot;position:relative;&quot;&gt;Requirements&lt;a href=&quot;#Requirements&quot; aria-label=&quot;Requirements permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Create a palindrome checker&lt;/li&gt;
&lt;li&gt;It should be able to detect that a string is a palindrome: that is, it is the same word or phrase in reverse.&lt;/li&gt;
&lt;li&gt;Words like &quot;mom&quot; are palindromes&lt;/li&gt;
&lt;li&gt;Words like &quot;bill&quot; aren&apos;t palindromes&lt;/li&gt;
&lt;li&gt;It should still know that something is a palindrome, even if the casing is off. So that means that &quot;Mom&quot; is still a palindrome.&lt;/li&gt;
&lt;li&gt;It should also be able to detect palindromes in phrases like &quot;Was It A Rat I Saw&quot; and &quot;Never Odd or Even&quot; too.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Rules&quot; style=&quot;position:relative;&quot;&gt;Rules&lt;a href=&quot;#Rules&quot; aria-label=&quot;Rules permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;So we know we&apos;re going &lt;em&gt;Red-Green-Refactor&lt;/em&gt;. According to Robert. C Martin, &lt;em&gt;the three rules of TDD&lt;/em&gt; for this are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;You are not allowed to write any production code&lt;/strong&gt; unless it is to make a failing unit test pass&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You are not allowed to write any more of a unit test than is sufficient to fail&lt;/strong&gt;; and compilation failures are failures.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You are not allowed to write any more production code&lt;/strong&gt; than is sufficient to pass the one failing unit test&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;Getting-started&quot; style=&quot;position:relative;&quot;&gt;Getting started&lt;a href=&quot;#Getting-started&quot; aria-label=&quot;Getting started permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I recommend trying this example as well using the &lt;a href=&quot;https://khalilstemmler.com/blogs/typescript/node-starter-project/&quot;&gt;Simple TypeScript Starter repo.&lt;/a&gt; To get started, paste this command in your terminal.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone https://github.com/stemmlerjs/simple-typescript-starter.git
&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; simple-typescript-starter
&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run test:dev&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;1-Write-the-failing-test&quot; style=&quot;position:relative;&quot;&gt;1. Write the failing test&lt;a href=&quot;#1-Write-the-failing-test&quot; aria-label=&quot;1 Write the failing test permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The first test I&apos;ll write is that the palindrome checker can tell that &quot;mom&quot; is a palindrome. I will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Write the test name using the requirements&lt;/li&gt;
&lt;li&gt;Pretend that something called &lt;code class=&quot;language-text&quot;&gt;palindromeChecker&lt;/code&gt; exists and that it has an &lt;code class=&quot;language-text&quot;&gt;isAPalindrome&lt;/code&gt; method on it.&lt;/li&gt;
&lt;li&gt;Expect the method to return &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt; for &lt;code class=&quot;language-text&quot;&gt;mom&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;/ul&gt;
&lt;p class=&quot;filename&quot;&gt;index.spec.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;palindrome checker&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 
  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;mom&quot; is a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;mom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ❌ &lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At this point, our &lt;strong&gt;test should be failing&lt;/strong&gt; because nothing named &lt;code class=&quot;language-text&quot;&gt;palindromeChecker&lt;/code&gt; exists and it doesn&apos;t have an &lt;code class=&quot;language-text&quot;&gt;isAPalindromeMethod&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/intro/red-green-refactor-red.png&quot; alt=&quot;Red-Green-Refactor&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;2-Write-the-simplest-code-to-make-the-test-pass&quot; style=&quot;position:relative;&quot;&gt;2. Write the simplest code to make the test pass&lt;a href=&quot;#2-Write-the-simplest-code-to-make-the-test-pass&quot; aria-label=&quot;2 Write the simplest code to make the test pass permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&apos;s move to green. In this next step, we:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a &lt;code class=&quot;language-text&quot;&gt;PalindromeChecker&lt;/code&gt; class&lt;/li&gt;
&lt;li&gt;Give it an &lt;code class=&quot;language-text&quot;&gt;isAPalindrome&lt;/code&gt; method&lt;/li&gt;
&lt;li&gt;Return &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt; (the simplest thing that would work)&lt;/li&gt;
&lt;li&gt;and import it in our test&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Implementing this, the &lt;code class=&quot;language-text&quot;&gt;index.ts&lt;/code&gt; containing our &lt;code class=&quot;language-text&quot;&gt;PalindromeChecker&lt;/code&gt; looks like this:&lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;index.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// This is the simplest thing!&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And our test file now looks like this:&lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;index.spec.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; PalindromeChecker &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./index&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;palindrome checker&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 
	&lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;mom&quot; is a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; palindromeChecker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;mom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ &lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Our test passes 🎉.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/intro/red-green-refactor-green.png&quot; alt=&quot;Red-Green-Refactor Green&quot;&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s move to the next step.&lt;/p&gt;
&lt;h3 id=&quot;3-Refactor&quot; style=&quot;position:relative;&quot;&gt;3. Refactor&lt;a href=&quot;#3-Refactor&quot; aria-label=&quot;3 Refactor permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When refactoring, keep a lookout for &lt;strong&gt;duplication (at least three times)&lt;/strong&gt; and &lt;strong&gt;code smells&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/intro/red-green-refactor-refactor.png&quot; alt=&quot;Red-Green-Refactor&quot;&gt;&lt;/p&gt;
&lt;p&gt;However... There&apos;s none here yet, so let&apos;s move to the next failing test.&lt;/p&gt;
&lt;h3 id=&quot;4-The-next-failing-test&quot; style=&quot;position:relative;&quot;&gt;4. The next failing test&lt;a href=&quot;#4-The-next-failing-test&quot; aria-label=&quot;4 The next failing test permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&apos;s grab the next test. We&apos;re going to test that &quot;bill&quot; &lt;em&gt;isn&apos;t&lt;/em&gt; a palindrome. Our tests should look something like this now.&lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;index.spec.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; PalindromeChecker &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./index&apos;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;palindrome checker&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;mom&quot; is a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; palindromeChecker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;mom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;bill&quot; isnt a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;	  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; palindromeChecker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;bill&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeFalsy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ❌ &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since our test fails, we&apos;re in the &lt;em&gt;red&lt;/em&gt; phase.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/intro/red-green-refactor-red.png&quot; alt=&quot;Red-Green-Refactor&quot;&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s turn it green.&lt;/p&gt;
&lt;h3 id=&quot;5-Write-the-simplest-code-to-make-the-test-pass&quot; style=&quot;position:relative;&quot;&gt;5. Write the simplest code to make the test pass&lt;a href=&quot;#5-Write-the-simplest-code-to-make-the-test-pass&quot; aria-label=&quot;5 Write the simplest code to make the test pass permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Currently, this is what our &lt;code class=&quot;language-text&quot;&gt;PalindromeChecker&lt;/code&gt; class looks like:&lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;index.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// This is the simplest thing!&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are &lt;strong&gt;several ways to go from Red to Green&lt;/strong&gt;. If we&apos;re really writing the &lt;em&gt;simplest possible thing that would work&lt;/em&gt;, then we&apos;d likely find no simpler thing to do than this: &lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;index.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;mom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But we know where this leads — so let&apos;s implement the &lt;em&gt;Obvious Implementation&lt;/em&gt; of reversing the string and seeing if it matches the originally provided one.&lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;index.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; reversed &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; reversed &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And if we save that, we should notice that our test passes.&lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;index.spec.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; PalindromeChecker &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./index&apos;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;palindrome checker&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;mom&quot; is a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; palindromeChecker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;mom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;bill&quot; isnt a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; palindromeChecker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;bill&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeFalsy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nice — now we&apos;re in &lt;em&gt;Green&lt;/em&gt; again.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/intro/red-green-refactor-green.png&quot; alt=&quot;red-green-refactor-green&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;6-Refactor&quot; style=&quot;position:relative;&quot;&gt;6. Refactor&lt;a href=&quot;#6-Refactor&quot; aria-label=&quot;6 Refactor permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Refactoring doesn&apos;t just mean refactoring production code. It means refactoring our test code too. And you may have noticed that there&apos;s some duplication in our test setup.&lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;index.spec.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; PalindromeChecker &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./index&apos;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;palindrome checker&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;mom&quot; is a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; palindromeChecker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;mom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;bill&quot; isnt a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; palindromeChecker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;bill&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeFalsy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;However, we&apos;re going to use the &lt;em&gt;Rule of Three&lt;/em&gt; to remove duplication. So we&apos;ll leave it for now.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;[Principle]: Use the Rule of Three to remove duplication —&lt;/b&gt;Introducing abstractions too early is one cause of poor design. Let&apos;s wait until we see duplication &lt;i&gt;three times&lt;/i&gt; before we make an effort to refactor it.&lt;/p&gt;
&lt;h3 id=&quot;7-The-next-failing-test&quot; style=&quot;position:relative;&quot;&gt;7. The next failing test&lt;a href=&quot;#7-The-next-failing-test&quot; aria-label=&quot;7 The next failing test permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The last test I&apos;ll demonstrate is the test case that specifies that a word is still a palindrome, even if it includes capitals and lowercase letters. The business rule here dictates that a word is a palindrome regardless of if it is capitalized or not.&lt;/p&gt;
&lt;p&gt;Let&apos;s write the failing test.&lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;index.spec.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; PalindromeChecker &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./index&apos;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;palindrome checker&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;mom&quot; is a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; palindromeChecker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;mom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;bill&quot; isnt a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; palindromeChecker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;bill&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeFalsy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should still detect a palindrome even if the casing is off&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; palindromeChecker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Mom&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ❌ &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Aha! &lt;em&gt;Look.&lt;/em&gt; We have that duplication we were talking about a moment ago. &lt;strong&gt;But we&apos;re not in the refactor phase yet&lt;/strong&gt;. We&apos;re about to turn this &lt;em&gt;Red&lt;/em&gt; test &lt;em&gt;Green&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/intro/red-green-refactor-red.png&quot; alt=&quot;Red-Green-Refactor&quot;&gt;&lt;/p&gt;
&lt;p&gt;We impose a little bit of discipline here and shift our focus to making this test pass.&lt;/p&gt;
&lt;h3 id=&quot;8-Write-the-simplest-code-to-make-the-test-pass&quot; style=&quot;position:relative;&quot;&gt;8. Write the simplest code to make the test pass&lt;a href=&quot;#8-Write-the-simplest-code-to-make-the-test-pass&quot; aria-label=&quot;8 Write the simplest code to make the test pass permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;At first glance, the simplest thing to do is to merely add &lt;code class=&quot;language-text&quot;&gt;.toLowerCase()&lt;/code&gt; to both the original and the reversed strings. So let&apos;s do that.&lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;index.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; reversed &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; reversed&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And if we save it and check our tests, we should see it pass as well.&lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;index.spec.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; PalindromeChecker &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./index&apos;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;palindrome checker&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;mom&quot; is a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; palindromeChecker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;mom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;bill&quot; isnt a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; palindromeChecker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;bill&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeFalsy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should still detect a palindrome even if the casing is off&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; palindromeChecker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Mom&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/intro/red-green-refactor-green.png&quot; alt=&quot;Red-Green-Refactor&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;9-Refactor&quot; style=&quot;position:relative;&quot;&gt;9. Refactor&lt;a href=&quot;#9-Refactor&quot; aria-label=&quot;9 Refactor permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;And now that we&apos;re in the refactor phase, we can look to improving that duplication we saw earlier.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tdd/intro/red-green-refactor-refactor.png&quot; alt=&quot;Red-Green-Refactor&quot;&gt;&lt;/p&gt;
&lt;p&gt;Jest, our test runner, has &lt;a href=&quot;https://jestjs.io/docs/setup-teardown&quot;&gt;a way to specify things that we must do &lt;em&gt;before each&lt;/em&gt; test&lt;/a&gt;. And creating the &lt;code class=&quot;language-text&quot;&gt;PalindromeChecker&lt;/code&gt; is what we&apos;d like to do here.&lt;/p&gt;
&lt;p&gt;We can clean up our code with the following:&lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;index.spec.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; PalindromeChecker &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./index&apos;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;palindrome checker&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; palindromeChecker&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PalindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token function&quot;&gt;beforeEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    palindromeChecker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;mom&quot; is a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;mom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;bill&quot; isnt a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;bill&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeFalsy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should still detect a palindrome even if the casing is off&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Mom&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ✅ &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That looks good to me! &lt;/p&gt;
&lt;h3 id=&quot;Continue&quot; style=&quot;position:relative;&quot;&gt;Continue&lt;a href=&quot;#Continue&quot; aria-label=&quot;Continue permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We can continue on like this by writing more and more failing tests, making the code more generic to make them pass, and improving the design. &lt;/p&gt;
&lt;p&gt;I&apos;ll leave the next two tests for you to do.&lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;index.spec.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; PalindromeChecker &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./index&apos;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;palindrome checker&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; palindromeChecker&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PalindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;beforeEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    palindromeChecker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PalindromeChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;mom&quot; is a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;mom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;bill&quot; isnt a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;bill&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeFalsy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should still detect a palindrome even if the casing is off&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;palindromeChecker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Mom&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBeTruthy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;Was It A Rat I Saw&quot; is a palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// You do this one!&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;should be able to tell that &quot;Never Odd or Even&quot; is palindrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// And this one!&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&apos;ve covered a lot of ground here.&lt;/p&gt;
&lt;p&gt;We discussed why we want to write tests, what TDD is and why it&apos;s important, what it looks like in the real world, and we demonstrated the basic technique: implementing the Red-Green-Refactor loop using &lt;em&gt;Classic TDD&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Homework&quot; style=&quot;position:relative;&quot;&gt;Homework&lt;a href=&quot;#Homework&quot; aria-label=&quot;Homework permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Master the Classic TDD technique. This should feel like breathing before we jump into Outside-In TDD and combine &apos;em to do Double Loop TDD. Try the Red-Green-Refactor process out on more coding katas.&lt;/li&gt;
&lt;li&gt;Try this out when you&apos;re building your domain objects (like &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-value-object/&quot;&gt;value objects&lt;/a&gt; and &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/entities/&quot;&gt;entities&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Next-in-the-series&quot; style=&quot;position:relative;&quot;&gt;Next in the series&lt;a href=&quot;#Next-in-the-series&quot; aria-label=&quot;Next in the series permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/articles/test-driven-development/how-to-test-code-coupled-to-apis-or-databases/&quot;&gt;How to Test Code Coupled to APIs or Databases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;More coming&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;You also likely have questions at this point:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;how do you write acceptance tests on the front-end&quot;?&lt;/li&gt;
&lt;li&gt;&quot;what is the difference between an acceptance test and an integration test&quot;?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In that case, leave a question in the comments down below or let me know what you&apos;d specifically like to see.&lt;/p&gt;
&lt;p&gt;To see where we&apos;re going next with this series, check out &lt;a href=&quot;https://twitter.com/khalilstemmler/status/1371239905637056515&quot;&gt;this twitter thread&lt;/a&gt; and take a look at the &lt;a href=&quot;https://twitter.com/khalilstemmler/status/1374459696183058437&quot;&gt;new outline for solidbook.io&lt;/a&gt;. &lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;span id=&quot;fn-1&quot;&gt;[1]&lt;/span&gt;: Some developers see programming as an art, math, science, etc. I think there are really good arguments for all of these ways to look at programming, but here&apos;s my way of thinking. If you&apos;re being paid to write code to make money, save money, or protect revenue, then you should treat the work you do as a craft, because the negative economic consequences for doing it poorly far contrast those of programming for exploratory, experimental, philosophical, or creative reasons.&lt;/p&gt;
&lt;p&gt;&lt;span id=&quot;fn-2&quot;&gt;[2]&lt;/span&gt;: There are two broad-stroke categories of test: white box and black box. White box testing is more concerned with what&apos;s on the inside. You could say these are tests for the developer. Black box tests are more concerned with the observable output and less about the internals or what&apos;s going on &lt;em&gt;within&lt;/em&gt; the code. You could call these tests for the customer. When we refer to &lt;em&gt;testable code&lt;/em&gt;, we&apos;re referring to the &lt;em&gt;mean&lt;/em&gt; between these two extremes. If your application adhered to &lt;a href=&quot;https://khalilstemmler.com/articles/oop-design-principles/command-query-separation/&quot;&gt;CQS&lt;/a&gt; and a query doesn&apos;t change the system, then you could technically &lt;em&gt;black box test&lt;/em&gt; any badly written code from the outside. It is significantly more difficult (maybe even sometimes impossible) to successfully &lt;em&gt;white box&lt;/em&gt; test badly written code. This is why it&apos;s a good idea to treat tests as architecture - to start with it before writing any code.&lt;/p&gt;
&lt;p&gt;&lt;span id=&quot;fn-3&quot;&gt;[3]&lt;/span&gt;: Architecturally speaking, there is &lt;i&gt;core code&lt;/i&gt; and there is &lt;i&gt;infrastructure code&lt;/i&gt;. Core code is the code that you use your hands to write. On the backend, with respect to the &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/organizing-app-logic/&quot;&gt;clean or hexagonal architecture&lt;/a&gt;, this is application and domain-layer code. On the front-end, with respect to &lt;a href=&quot;https://khalilstemmler.com/articles/client-side-architecture/layers/&quot;&gt;client-side architectural layers&lt;/a&gt;, this is the interaction layer and UI logic. It&apos;s the code that you own. Infrastructure code is the stuff that you don&apos;t own. Databases, caches, and web servers on the backend and view layer libraries, GraphQL clients, browser APIs and HTTP clients on the front-end. &lt;strong&gt;In the real-world, we use both&lt;/strong&gt;. And this is where many of our testing challenges arise. How do we decouple our core code from the infrastructure code so that we can test &lt;em&gt;our&lt;/em&gt; code, and test it &lt;em&gt;fast&lt;/em&gt;? These are questions that are better asked and answered earlier than later on in a project.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[GraphQL Schemas vs. RESTful DTOs]]></title><description><![CDATA[In the last post, I mentioned the fact that DTOs (Data Transfer Objects) and GraphQL schemas serve a similar purpose; they create a strict…]]></description><link>https://khalilstemmler.com/articles/graphql/graphql-schemas-vs-restful-dtos/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/graphql/graphql-schemas-vs-restful-dtos/</guid><pubDate>Fri, 12 Mar 2021 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;In &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/use-dtos-to-enforce-a-layer-of-indirection/&quot;&gt;the last post&lt;/a&gt;, I mentioned the fact that &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/repository-dto-mapper/#Data-Transfer-Objects&quot;&gt;DTOs (Data Transfer Objects)&lt;/a&gt; and GraphQL schemas serve a similar purpose; they create a &lt;strong&gt;strict&lt;/strong&gt; &lt;em&gt;abstraction layer&lt;/em&gt; that the client (web, mobile, or desktop apps) can rely on. This leaves backend services to merely figure out how to implement the data.&lt;/p&gt;
&lt;p&gt;It creates a relationship that looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/vs-dtos/clients-rely-on-dtos.svg&quot; alt=&quot;GraphQL%20Schemas%20vs%20RESTful%20DTOs%20acaad35cee444cdd97b85059e5e8cb00/clients-rely-on-dtos.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you&apos;re a &lt;a href=&quot;https://khalilstemmler.com/newsletter&quot;&gt;subscriber&lt;/a&gt; here, you know that I value the emails I get in response to my &lt;a href=&quot;https://khalilstemmler.com/newsletter&quot;&gt;bi-weekly newsletters&lt;/a&gt;. One reader wasn&apos;t so convinced about the similarities between GraphQL schemas and RESTful DTOs in the last post and had some criticisms to share (&lt;em&gt;thank you for doing so&lt;/em&gt;). &lt;/p&gt;
&lt;p&gt;In this post, I&apos;d like to examine those criticisms for GraphQL as a RESTful replacement and share some principles for managing graphs in production.&lt;/p&gt;
&lt;h2 id=&quot;Opinion-GraphQL-exposes-everything&quot; style=&quot;position:relative;&quot;&gt;Opinion: GraphQL exposes everything&lt;a href=&quot;#Opinion-GraphQL-exposes-everything&quot; aria-label=&quot;Opinion GraphQL exposes everything permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The first piece of criticism was:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;A DTO &lt;em&gt;explicitly&lt;/em&gt; limits what is exposed to the client, whereas I&apos;m finding with GraphQL that developers feel encouraged to expose everything but the kitchen sink up front.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here, the reader is referring to the fact that to create a DTO, we need to explicitly type it out by hand. &lt;/p&gt;
&lt;p&gt;For example, a DTO for a vinyl-trading application, say &lt;code class=&quot;language-text&quot;&gt;VinylDTO&lt;/code&gt;, could be composed to look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Genre &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Post-punk&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Trip-hop&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Rock&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Rap&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Electronic&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Pop&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TrackDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  length&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; TrackCollectionDTO &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TrackDTO&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Vinyl view model / DTO, this is the format of the response&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  albumName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  label&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  country&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  yearReleased&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  artistName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  trackList&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TrackCollectionDTO&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You may be looking at that and thinking, &quot;man — this sure does look a lot like a &lt;em&gt;GraphQL schema&lt;/em&gt;&quot;. And I&apos;d opt to agree with you there. The GraphQL schema version of this might look like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Genre&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  PostPunk&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  TripHop&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  Rock&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  Rap&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  Electronic&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  Pop
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Track&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;albumName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;country&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;yearReleased&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;genres&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Genre&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;artistName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;trackList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Track&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So where are we getting the &quot;developers feel encouraged to expose everything but the kitchen sink upfront&quot; sentiment from?&lt;/p&gt;
&lt;p&gt;I think it&apos;s coming from the fact that &lt;strong&gt;there are tools out there to auto-generate GraphQL CRUD APIs for you&lt;/strong&gt;. In those cases, if you&apos;re intending to use your auto-generated GraphQL API as your public GraphQL API, then yes — you&apos;re exposing everything to the client.&lt;/p&gt;
&lt;p&gt;But this simply just isn&apos;t the way we recommend building GraphQL APIs at Apollo.&lt;/p&gt;
&lt;p&gt;Have you read &lt;em&gt;Principled GraphQL&lt;/em&gt;?&lt;/p&gt;
&lt;h3 id=&quot;Principled-GraphQL&quot; style=&quot;position:relative;&quot;&gt;Principled GraphQL&lt;a href=&quot;#Principled-GraphQL&quot; aria-label=&quot;Principled GraphQL permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://principledgraphql.com/?utm_source=khalil&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=graphql-vs-dtos&quot;&gt;Principled GraphQL&lt;/a&gt; is Apollo&apos;s best practices guide for creating, maintaining, and operating a data graph. It&apos;s what we practice and preach at Apollo.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/vs-dtos/principled-graphql.png&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;As someone who maintains a website about software design principles and best practices, I really respect the fact that Principled GraphQL puts a stake in the ground for what it means to do GraphQL properly. It&apos;s written by the founders of Apollo based on thousands of conversations with developers implementing GraphQL at companies of all sizes. Conversations with those with practical experience; now that&apos;s the way to discover &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Phronesis&quot;&gt;phronesis&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Principle #5&lt;/em&gt; is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Use An Agile Approach to Schema Development&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;One of the main ideas about this principle is that &quot;each field should be added only in response to a concrete need by a consumer for additional functionality&quot;. &lt;/p&gt;
&lt;p&gt;This means that &lt;strong&gt;schema design is an iterative process&lt;/strong&gt; and &lt;strong&gt;you should only be adding things to your graph that is actually needed by the consumers of your graph&lt;/strong&gt;. This means collaboration. It means conversations. This is &quot;&lt;a href=&quot;https://khalilstemmler.com/articles/graphql/ddd/schema-design/&quot;&gt;Domain-Driven GraphQL Schema Design&lt;/a&gt;&quot;. &lt;/p&gt;
&lt;p&gt;Any field not explicitly and decidedly needed by the client is an &lt;em&gt;implementation detail&lt;/em&gt;. It&apos;s likely that there are some things in your database that shouldn&apos;t be exposed to the client directly. For example, if you were doing CQRS, in a &lt;a href=&quot;https://khalilstemmler.com/articles/oop-design-principles/command-query-separation/&quot;&gt;command&lt;/a&gt;, there could exist an &lt;a href=&quot;https://khalilstemmler.com/wiki/invariant/&quot;&gt;invariant&lt;/a&gt; within an &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;aggregate&lt;/a&gt; that operates on a particular piece of state that doesn&apos;t have a read model equivalent. Consider an insurance application. You might assign a user a score and save that to their profile. Perhaps it determines what they get approved for. Perhaps this is something that you don&apos;t want to expose to the client directly.&lt;/p&gt;
&lt;h2 id=&quot;Opinion-You-cant-change-already-added-fields&quot; style=&quot;position:relative;&quot;&gt;Opinion: You can&apos;t change already added fields&lt;a href=&quot;#Opinion-You-cant-change-already-added-fields&quot; aria-label=&quot;Opinion You cant change already added fields permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The other main piece of criticism I noticed was that you can&apos;t change fields. They said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;The server must still maintain all of the fields it initially made available or risk breaking clients&quot;, and &quot;now there is no backing out.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I can see why you&apos;d think that, but there &lt;em&gt;is&lt;/em&gt; backing out. &lt;/p&gt;
&lt;p&gt;GraphQL APIs are tasked with the same set of challenges that any API layer technology is tasked with. Among those challenges, the big question of &quot;how do we make changes to the API and deprecate parts of it over time&quot; arises. &lt;/p&gt;
&lt;p&gt;Well, &lt;strong&gt;in GraphQL there&apos;s no concept of an API version&lt;/strong&gt; like v1 or v2 in REST. Such a way to version your API is coarse and can become quite an engineering effort. &lt;/p&gt;
&lt;p&gt;Instead, GraphQL gives you a declarative and &lt;strong&gt;fine-grained way to keep track of, evolve, and deprecate parts of your API&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Use-a-schema-registry&quot; style=&quot;position:relative;&quot;&gt;Use a schema registry&lt;a href=&quot;#Use-a-schema-registry&quot; aria-label=&quot;Use a schema registry permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Principle #3&lt;/em&gt; is to:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Track the Schema in a Registry&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Similar to how we track source code in Git, the idea is that we should be tracking what our graph looks like overtime in a schema registry.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/vs-dtos/dos-and-donts-graphql-schema-design.png&quot; alt=&quot;Do&amp;#x27;s and Don&amp;#x27;ts of GraphQL Schema Design&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;I highly recommend the talk, &quot;&lt;a target=&quot;_blank&quot; href=&quot;https://www.youtube.com/watch?v=fG8zy1OROp4&amp;ab_channel=ApolloGraphQL&quot;&gt;The Do&apos;s and Don&apos;ts of GraphQL Schema Design&lt;/a&gt;&quot; by Michael Watson — Solutions Engineer at Apollo.&lt;/p&gt;
&lt;p&gt;The schema registry keeps track of the history of the graph and it can be used to model &lt;a href=&quot;https://www.apollographql.com/blog/graphql-roles-and-protected-variants/&quot;&gt;graph variants&lt;/a&gt; (like example, staging, production, or dev branches).&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;
&lt;b&gt;How to track your schema in a registry&lt;/b&gt;: You can get started with a &lt;a target=&quot;_blank&quot; href=&quot;https://studio.apollographql.com/dev?utm_source=blog&amp;utm_medium=website&amp;utm_campaign=2021_03_dtos-and-graphql-schemas&quot;&gt;local dev graph&lt;/a&gt; in Apollo Studio and then publish variants of your graph to a managed schema registry when you&apos;re ready. Read &lt;a target=&quot;_blank&quot; href=&quot;https://www.apollographql.com/docs/studio/schema/schema-reporting/&quot;&gt;the docs on schema reporting&lt;/a&gt; and &lt;a target=&quot;_blank&quot; href=&quot;https://studio.apollographql.com/dev?utm_source=blog&amp;utm_medium=website&amp;utm_campaign=2021_03_dtos-and-graphql-schemas&quot;&gt;get started with a local graph here&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;Now, if you&apos;re familiar with REST — you&apos;ve probably set up different example, staging, and production environments before. Not much difference there besides a more explicit and declarative way to do this.&lt;/p&gt;
&lt;p&gt;The next part is uniquely GraphQL.&lt;/p&gt;
&lt;h3 id=&quot;Deprecating-fields&quot; style=&quot;position:relative;&quot;&gt;Deprecating fields&lt;a href=&quot;#Deprecating-fields&quot; aria-label=&quot;Deprecating fields permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; deprecate old fields. Here&apos;s what that might look like in your schema:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ExampleType&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;oldField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String &lt;span class=&quot;token directive function&quot;&gt;@deprecated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;reason&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Use `newField`.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;newField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;GraphQL gives you the ability to deprecate fields, signaling to clients that they should probably use the new fields, with GraphQL directives.&lt;/p&gt;
&lt;p&gt;That&apos;s great and all, but how do we do this &lt;em&gt;safely&lt;/em&gt;?&lt;/p&gt;
&lt;h3 id=&quot;Client-awareness&quot; style=&quot;position:relative;&quot;&gt;Client awareness&lt;a href=&quot;#Client-awareness&quot; aria-label=&quot;Client awareness permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Apollo has a cloud platform with a variety of tools that help you build, explore, and manage your graph in production: it&apos;s called &lt;a href=&quot;https://studio.apollographql.com/dev?utm_source=blog&amp;#x26;utm_medium=website&amp;#x26;utm_campaign=2021_03_dtos-and-graphql-schemas&quot;&gt;Apollo Studio&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;One of the many features in Apollo Studio is GraphQL &quot;&lt;a href=&quot;https://www.apollographql.com/blog/how-apollo-studio-client-awareness-improved-our-lives/&quot;&gt;Client Awareness&lt;/a&gt;&quot;. Client awareness lets you know &lt;strong&gt;ahead of time&lt;/strong&gt; &lt;em&gt;which clients&lt;/em&gt; are using &lt;em&gt;which fields&lt;/em&gt; in your Graph and &lt;strong&gt;how much traffic those fields get&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;This is probably one of the safest ways to know when you can pull a deprecated field from your graph.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/vs-dtos/graphql-client-awareness.png&quot; alt=&quot;GraphQL%20Schemas%20vs%20RESTful%20DTOs%20acaad35cee444cdd97b85059e5e8cb00/Untitled.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;With this tool, a workflow to deprecate and update a field might look like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a new field and deprecate the old one using the &lt;code class=&quot;language-text&quot;&gt;@deprecated&lt;/code&gt; directive (perhaps optionally recommending the new field to use instead).&lt;/li&gt;
&lt;li&gt;Publish the graph changes to a schema registry.&lt;/li&gt;
&lt;li&gt;Give teams time to start using the new field.&lt;/li&gt;
&lt;li&gt;Check Apollo Studio to confirm that the new field&apos;s traffic is ~zero.&lt;/li&gt;
&lt;li&gt;Create a PR to remove the old field.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/vs-dtos/update-pr.png&quot;&gt;&lt;/p&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;Deploy the change to production.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;GraphQL schemas create a &lt;strong&gt;strict&lt;/strong&gt; &lt;em&gt;abstraction layer&lt;/em&gt; between the client and the backend services, similar to DTOs in REST. Since they&apos;re both API layer constructs, they share a lot of the same problems. What we&apos;ve found makes the real difference is &lt;strong&gt;a principled approach&lt;/strong&gt; and &lt;strong&gt;great tooling&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Recommended&quot; style=&quot;position:relative;&quot;&gt;Recommended&lt;a href=&quot;#Recommended&quot; aria-label=&quot;Recommended permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=fG8zy1OROp4&amp;#x26;ab_channel=ApolloGraphQL&quot;&gt;The Do’s and Don’ts for your schema and GraphQL operations&lt;/a&gt; by &lt;a href=&quot;https://twitter.com/ThreeBrewMates&quot;&gt;Michael Watson&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://principledgraphql.com/&quot;&gt;PrincipledGraphQL&lt;/a&gt; by Apollo&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/schema/directives/&quot;&gt;How to configure Apollo Server directives&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Use DTOs to Enforce a Layer of Indirection | Node.js w/ TypeScript]]></title><description><![CDATA[Have you ever heard the expression that "all problems in computer science can be solved by adding another layer of indirection"? I'm not…]]></description><link>https://khalilstemmler.com/articles/enterprise-typescript-nodejs/use-dtos-to-enforce-a-layer-of-indirection/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/enterprise-typescript-nodejs/use-dtos-to-enforce-a-layer-of-indirection/</guid><pubDate>Wed, 24 Feb 2021 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Have you ever heard the expression that &quot;&lt;strong&gt;all problems in computer science can be solved by adding another layer of indirection&quot;&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;I&apos;m not sure about &lt;em&gt;all&lt;/em&gt;, but if the &lt;em&gt;structural problems&lt;/em&gt; in software design can be reduced to being either an issue with &lt;a href=&quot;https://khalilstemmler.com/wiki/coupling-cohesion-connascence/&quot;&gt;coupling or cohesion&lt;/a&gt;, then yeah - this makes a lot of sense.&lt;/p&gt;
&lt;h3 id=&quot;Indirection&quot; style=&quot;position:relative;&quot;&gt;Indirection&lt;a href=&quot;#Indirection&quot; aria-label=&quot;Indirection permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To understand the concept of &lt;em&gt;indirection&lt;/em&gt;, we need to understand the fact that software doesn&apos;t do a whole lot unless we can connect things together. This means that components (whether it be a class, object, package, server, or client application) typically rely on other components to do something meaningful.&lt;/p&gt;
&lt;p&gt;Take &lt;strong&gt;web applications&lt;/strong&gt; for example. Most web applications implement the client-server architecture. This usually means that the &lt;em&gt;client&lt;/em&gt; relies on the &lt;em&gt;server.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/enterprise-node/indirection/client-relies-on-server.svg&quot; alt=&quot;Client relies on server&quot;&gt;&lt;/p&gt;
&lt;p&gt;And if we&apos;re being realistic, it&apos;s a lot more likely that there will be several clients that rely on the server (like a web, mobile, and desktop client). Notion is a great example of this. They have a web, mobile, and desktop app.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/enterprise-node/indirection/clients-rely-on-server.svg&quot; alt=&quot;Clients rely on server&quot;&gt;&lt;/p&gt;
&lt;p&gt;In this &lt;em&gt;dependency relationship&lt;/em&gt;, the &lt;strong&gt;clients rely on the server&lt;/strong&gt;. A lot. It means that if, for some reason, the server were to change things or break, that change or breakage has the potential to &lt;strong&gt;ripple into each client that relies on it&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This is the nature of &lt;a href=&quot;https://khalilstemmler.com/wiki/coupling-cohesion-connascence/#Coupling&quot;&gt;tight coupling&lt;/a&gt;. It puts the clients in an awkward position of needing to constantly keep on top of the latest changes to the server and protect itself against failure. A substantial change could break the entire client. This isn&apos;t great. Not great at all.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;In fact, just this week, I realized that the browsers introduced a new security feature called &lt;a target=&quot;_blank&quot; href=&quot;https://developers.google.com/web/updates/2020/07/referrer-policy-new-chrome-default#:~:text=for%20more%20details.-,What%20does%20this%20change%20mean%3F,the%20path%20and%20query%20string.&quot;&gt;strict-origin-when-cross-origin&lt;/a&gt; that was stopping &lt;a target=&quot;_blank&quot; href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt; readers from getting into the online Wiki. Since my application depends on the browser, it means I&apos;ll always have to keep on top of things the browser does that could cause my app to break.&lt;/p&gt;
&lt;p&gt;What can we do about this problem?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Introduce a layer of indirection&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let me walk you through a real-world example of how to use &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;DTOs — Data-Transfer Objects&lt;/a&gt; to &lt;strong&gt;introduce stability and protect clients from change in a RESTful API&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;A-trivial-RESTful-API-controller&quot; style=&quot;position:relative;&quot;&gt;A trivial RESTful API controller&lt;a href=&quot;#A-trivial-RESTful-API-controller&quot; aria-label=&quot;A trivial RESTful API controller permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Consider this very stripped down, simple controller that pulls the current user and returns a raw Sequelize ORM object as a result of the &lt;code class=&quot;language-text&quot;&gt;GetCurrentUser&lt;/code&gt; RESTful API call.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;GetCurrentUserController&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;sequelize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;decoded&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; sequelize&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; user_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; userId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For a long time, this is how I used to build out my controllers in my RESTful API layer. &lt;/p&gt;
&lt;p&gt;We&apos;re not doing anything fancy. We&apos;re just using an ORM to get the data we need and return it to the caller. Straightforward, right?&lt;/p&gt;
&lt;p&gt;What&apos;s the shape of the &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; object on our RESTful API? Because it&apos;s hooked up directly to our ORM, it&apos;ll return whatever &lt;em&gt;that&lt;/em&gt;, the ORM, returns. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Khalil&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Stemmler&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;khalil@khalilstemmler.com&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  isAdmin&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  isStudent&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  isEmployer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Cool. That&apos;s alright. The design could be better. But let&apos;s imagine that this is what we&apos;ve chosen and it&apos;s been like that for quite some time now. Consider that client teams have used our API and built things on top of it already.&lt;/p&gt;
&lt;p&gt;Now &lt;em&gt;this&lt;/em&gt; happens.&lt;/p&gt;
&lt;h3 id=&quot;We-want-to-change-the-API&quot; style=&quot;position:relative;&quot;&gt;We want to change the API&lt;a href=&quot;#We-want-to-change-the-API&quot; aria-label=&quot;We want to change the API permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After months of living with our design, we realize that we don&apos;t like it — particularly the &lt;code class=&quot;language-text&quot;&gt;isAdmin&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;isStudent&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;isEmployer&lt;/code&gt; part. &lt;/p&gt;
&lt;p&gt;We realize that we&apos;re moving towards having more and more &lt;em&gt;roles&lt;/em&gt; and that hard-coding the roles as a part of the &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; entity actually breaks domain encapsulation. The &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; entity has become somewhat coupled the specifics of other subdomains (&lt;code class=&quot;language-text&quot;&gt;students&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;jobs&lt;/code&gt;). &lt;/p&gt;
&lt;p&gt;An astute software designer may also recognize that this is a violation of the &lt;a href=&quot;https://khalilstemmler.com/articles/solid-principles/solid-typescript/#Open-Closed-Principle&quot;&gt;Open-Closed principle&lt;/a&gt;. A module should be open for extension but closed for modification, right? But it seems that every time we want to add a new role (ie: extend this entity&apos;s use case), we have to &lt;strong&gt;modify it directly&lt;/strong&gt; (by adding a new column to the database in the form of an &lt;code class=&quot;language-text&quot;&gt;is[role]&lt;/code&gt; structure). Not good.&lt;/p&gt;
&lt;p&gt;We goofed up here. That&apos;s OK. The design got us to this point, and that&apos;s what matters. We&apos;re here today and we want to refactor it.&lt;/p&gt;
&lt;p&gt;We decide that it would make more sense to have something like this instead:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Khalil&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Stemmler&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;khalil@khalilstemmler.com&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  roles&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Admin&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&apos;s much better. The concept of &lt;code class=&quot;language-text&quot;&gt;roles&lt;/code&gt; seems much more appropriate within a &lt;code class=&quot;language-text&quot;&gt;users&lt;/code&gt; subdomain. Not only that, but we&apos;re doing good by the Open-Closed Principle: we can extend this entity by &lt;em&gt;adding a role,&lt;/em&gt; not &lt;em&gt;changing the structure&lt;/em&gt; of the entity. &lt;/p&gt;
&lt;p&gt;Lovely. &lt;/p&gt;
&lt;p&gt;So, we go ahead and make the change by writing a Sequelize migration, &lt;strong&gt;looking through our code and changing every controller&lt;/strong&gt; &lt;strong&gt;that mentions a &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; to do the following.&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;GetCurrentUserController&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;sequelize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;decoded&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; sequelize&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
			where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; user_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; userId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;			include&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;				&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; sequelize&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Role&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Roles&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;			&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token comment&quot;&gt;// This is how we maintain the structure&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      isAdmin&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Roles&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Admin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      isStudent&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Roles&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Student&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      isEmployer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Roles&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Employer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Hopefully we&apos;ve found and changed every place in our codebase where we return a &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt;; because if we miss one, we might break the API for our clients.&lt;/p&gt;
&lt;h3 id=&quot;Disadvantages-to-this-approach&quot; style=&quot;position:relative;&quot;&gt;Disadvantages to this approach&lt;a href=&quot;#Disadvantages-to-this-approach&quot; aria-label=&quot;Disadvantages to this approach permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Not only is this messy, but even despite best efforts, it&apos;s too easy to break. Clients are practically hooked up directly to any changes we make to our database. There is almost no encapsulation from the implementation details.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/enterprise-node/indirection/clients-rely-on-server-broken.svg&quot; alt=&quot;Dec&quot;&gt;&lt;/p&gt;
&lt;p&gt;The main issues here are that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Our API is not stable&lt;/li&gt;
&lt;li&gt;It forces us to get the design absolutely correct the first time around (pretty unlikely)&lt;/li&gt;
&lt;li&gt;We&apos;ll have to scour our codebase for other places affected by database changes&lt;/li&gt;
&lt;li&gt;It makes implementing API changes incredibly hard&lt;/li&gt;
&lt;li&gt;Drives us to tolerate bad design decisions because changing them is just &lt;em&gt;too much of a hassle&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;And we know where this leads — it&apos;s the &lt;strong&gt;&lt;a href=&quot;https://blog.codinghorror.com/the-broken-window-theory/&quot;&gt;broken windows theory&lt;/a&gt;&lt;/strong&gt;. Software rot is just down the road.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Enforcing-a-layer-of-indirection&quot; style=&quot;position:relative;&quot;&gt;Enforcing a layer of indirection&lt;a href=&quot;#Enforcing-a-layer-of-indirection&quot; aria-label=&quot;Enforcing a layer of indirection permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Using-Data-Transfer-Objects&quot; style=&quot;position:relative;&quot;&gt;Using Data Transfer Objects&lt;a href=&quot;#Using-Data-Transfer-Objects&quot; aria-label=&quot;Using Data Transfer Objects permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;DTOs are data transfer objects. They&apos;re not much. They&apos;re simple interfaces or classes that represent the shape of your API. &lt;/p&gt;
&lt;p&gt;The idea is to use DTOs to create a &lt;strong&gt;contract for your API&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If we modelled the initial shape of the &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; entity as a part of our RESTful API, we&apos;d likely have a DTO that looked like this.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Number&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  isAdmin&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  isStudent&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  isEmployer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then we&apos;d use another pattern, the &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/repository-dto-mapper/#Data-Mappers&quot;&gt;data mapper pattern&lt;/a&gt;, to hold the responsibility of mapping the raw sequelize object to the correct DTO shape&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;GetCurrentUserController&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;sequelize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;UserDTO&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; =&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;decoded&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; sequelize&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
			where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; user_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; userId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			include&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; sequelize&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Role&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Roles&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; UserMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDTO&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This can be improved even further by encapsulating the ORM logic in a &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/repository-dto-mapper/#Repositories&quot;&gt;repository&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;GetCurrentUserController&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;UserDTO&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; =&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;decoded&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findUserByUserId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; UserMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDTO&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Advantages-to-this-approach&quot; style=&quot;position:relative;&quot;&gt;Advantages to this approach&lt;a href=&quot;#Advantages-to-this-approach&quot; aria-label=&quot;Advantages to this approach permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now instead of relying on the server (and everything the server relies on), the clients rely only on the DTOs.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/enterprise-node/indirection/clients-rely-on-dtos.svg&quot; alt=&quot;Relying on DTOs&quot;&gt;&lt;/p&gt;
&lt;p&gt;The advantages are that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The DTOs become a strict contract for our API. The clients rely on it. The server implements it.&lt;/li&gt;
&lt;li&gt;We&apos;ve implemented &lt;em&gt;architectural&lt;/em&gt; &lt;a href=&quot;https://khalilstemmler.com/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;dependency inversion&lt;/a&gt; between the client and the server.&lt;/li&gt;
&lt;li&gt;The DTOs act as a &lt;strong&gt;layer of indirection&lt;/strong&gt; and shield the clients from internal changes to the way the API is resolved.&lt;/li&gt;
&lt;li&gt;Data mappers act as a single location for object transformations. Instead of going through the codebase and changing API code that deals with raw sequelize users all over the place, it&apos;s done in one place.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If this smells a lot like the things GraphQL does, it&apos;s because it is. GraphQL acts as a strictly-typed &lt;strong&gt;abstraction&lt;/strong&gt; that clients &lt;em&gt;rely on&lt;/em&gt; and services &lt;em&gt;implement&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Different-objects-for-different-needs&quot; style=&quot;position:relative;&quot;&gt;Different objects for different needs&lt;a href=&quot;#Different-objects-for-different-needs&quot; aria-label=&quot;Different objects for different needs permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I think a layered architecture is one of the best things you can do for non-trivial web applications of complexity.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You have domain objects (that your domain layer needs), data transfer objects (that your clients need), and the raw sequelize objects (that your database needs). The mapper handles transformations between all of &apos;em.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;Continue-reading&quot; style=&quot;position:relative;&quot;&gt;Continue reading&lt;a href=&quot;#Continue-reading&quot; aria-label=&quot;Continue reading permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Want to learn how to do implement this in your next project?&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;Read the next post here: &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;Implementing DTOs, Mappers &amp; the Repository Pattern using the Sequelize ORM [with Examples] - DDD w/ TypeScript&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Transcribing Video With DDD Discussion | Domain Driven Design w/ TypeScript]]></title><description><![CDATA[I'm always interested in what blog readers are building using Domain-Driven Design and Clean Architecture practices.  In this post, I'd like…]]></description><link>https://khalilstemmler.com/blogs/domain-driven-design/transcribing-video-with-ddd-discussion/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/domain-driven-design/transcribing-video-with-ddd-discussion/</guid><pubDate>Mon, 22 Feb 2021 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;m always interested in what blog readers are building using Domain-Driven Design and Clean Architecture practices. &lt;/p&gt;
&lt;p&gt;In this post, I&apos;d like to share an email exchange I held with a reader who is working on encapsulating the complexity of building an application capable of &lt;em&gt;transcribing videos&lt;/em&gt; given their public URL.&lt;/p&gt;
&lt;p&gt;Very neat!&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;If this is something you&apos;re looking into doing, awesome. If not, hopefully this discussion is enriching anyway. I often like to be a fly on the wall in technical discussions, and by the law of the internet - I assume someone else must as well!&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi Khalil! I&apos;ve been impressed by your articles and I bought your online book, solidbook.io. And also I&apos;ve been practicing and introducing DDD in real projects.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Recently, I&apos;ve taken a task to handle streaming media. Download media files and reformat them. And transform the audio of media into a text. And then combine them into one media streaming like HLS with VTT. All of the above processes are conducted with &quot;stream&quot;. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;At this point I wonder how I can handle &quot;stream&quot; in DDD? Should I have to handle stream as domain object? Or infra? With traditional REST API app, I&apos;ve almost understood concept of DDD and applied several DDD to several projects. But it is not easy to handle things like stream :( Can you share your experience or inspiration? Thanks in advance :)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;&quot;Your question, &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Should I have to handle stream as domain object? Or infra?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The answer to your question is &lt;em&gt;likely&lt;/em&gt; both. Though it depends. I&apos;ll explain.&lt;/p&gt;
&lt;p&gt;First, let&apos;s recall the concept of &lt;strong&gt;high-level vs. low-level policy&lt;/strong&gt;. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;High-level policy is &lt;em&gt;what we do&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;low-level policy is &lt;em&gt;how we do it&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The high-level policy is the &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/organizing-app-logic/#Domain-Layer&quot;&gt;domain layer&lt;/a&gt; and the low-level policy is your &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/organizing-app-logic/#Infra-everything-else-layer&quot;&gt;infrastructure layer&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Domain layer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/entities/&quot;&gt;entities&lt;/a&gt; &amp;#x26; &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;aggregates&lt;/a&gt; — protects invariants around object behavior &amp;#x26; state changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/typescript-value-object/&quot;&gt;value objects&lt;/a&gt; — protects invariants around validation and object creation logic&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Infrastructure&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;repositories&lt;/a&gt; — object persistence and retrieval&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even &lt;em&gt;highly technical domains&lt;/em&gt; centered around expensive I/O things can benefit from decoupling the domain from infrastructure. Consider &lt;strong&gt;building a new database technology&lt;/strong&gt;, &lt;strong&gt;a virtual synthesizer,&lt;/strong&gt; or in your case — &lt;strong&gt;streaming media&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;These are all heavily I/O-heavy kinds of problems to solve. They interact with files, &lt;em&gt;upper-layer&lt;/em&gt; protocols, user inputs, and sound. A real-world example that comes to mind is actually what powers &lt;a href=&quot;https://wiki.solidbook.io&quot;&gt;wiki.solidbook.io&lt;/a&gt;. I wrote &lt;strong&gt;a library that converts Notion markdown pages into a website, PDF, and EPUB&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The domain layer has objects that represent these I/O concepts as domain objects.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-discussion-transcription/folder-contents.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;But the majority of the I/O lives in repositories. For example, if I wanted to create a file, I&apos;d create a &lt;code class=&quot;language-text&quot;&gt;file&lt;/code&gt; entity (high-level), the pass it to the &lt;code class=&quot;language-text&quot;&gt;fileRepo&lt;/code&gt; to persist it  to the file system (low-level) at the path specified by the &lt;code class=&quot;language-text&quot;&gt;getAbsoluteFilePath&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;The whole reason we use abstraction layers and decouple domain from infrastructure is to separate concerns, decompose complexity, and increase cohesion by &lt;a href=&quot;/articles/oop-design-principles/maintain-a-single-layer-of-abstraction/&quot;&gt;maintaining a single level of abstraction at a time&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;OK, Khalil — I get it. Now, how would you do this? How would you go about solving this?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Event Storming or Event Modelling&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Just like we walk through with the forum app we build in &lt;a href=&quot;https://wiki.solidbook.io&quot;&gt;solidbook&lt;/a&gt;, I&apos;d recommend you start with what you should do on &lt;em&gt;any&lt;/em&gt; domain-driven design project: use Event Storming or Event Modelling to discover the domain (ie: the high-level policy and &lt;em&gt;what&lt;/em&gt; we do).&lt;/p&gt;
&lt;p&gt;This is a collaborative activity that you&apos;d normally do with your team and domain experts (the customer or a representative for the customer), but I&apos;m making a ton of assumptions on my own here.&lt;/p&gt;
&lt;p&gt;Here&apos;s what I&apos;ve landed on (you might want to download or right-click and open in a new tab to see the image better).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-discussion-transcription/streaming-events.png&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Commands: &lt;code class=&quot;language-text&quot;&gt;StartStreamJob&lt;/code&gt; (this is the only public one done by the &lt;em&gt;user —&lt;/em&gt; the rest are done by the system itself), &lt;code class=&quot;language-text&quot;&gt;ExtractTextFromAudio&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;CombineMedia&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;CompleteStreamJob&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Events: &lt;code class=&quot;language-text&quot;&gt;StreamJobStarted&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;ExtractedTextFromAudio&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;CombinedMedia&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;StreamJobCompleted&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, this might not be exactly correct, but this is what I got from reading your email. You&apos;ll want to do this yourself with your team (which hopefully includes the customer or a representative for the customer like a product manager).&lt;/p&gt;
&lt;p&gt;We now have all the &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Next, we should probably discussion how much you want to handle vs. how much you want to outsource.&lt;/p&gt;
&lt;p&gt;Do you want to write the transcoding, transcribing, and reformatting logic &lt;em&gt;yourself&lt;/em&gt; or would you prefer to use a service that does it well already?&lt;/p&gt;
&lt;p&gt;I&apos;d personally recommend using a service like AWS. They have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Transcode/reformat — &lt;a href=&quot;https://aws.amazon.com/elastictranscoder/&quot;&gt;https://aws.amazon.com/elastictranscoder/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Transcribe Audio (get the text from audio) — &lt;a href=&quot;https://aws.amazon.com/transcribe/&quot;&gt;https://aws.amazon.com/transcribe/&lt;/a&gt;. For example, here&apos;s the API to &lt;a href=&quot;https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-transcribe/classes/transcribe.html#starttranscriptionjob&quot;&gt;start a transcription job&lt;/a&gt; using the Transcribe API.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This stuff is going to live in infrastructure. We&apos;ll write adapters for this, and if we want, we can switch any of these things out and write our own implementation. I imagine:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Transcoder interface — implemented by an &lt;code class=&quot;language-text&quot;&gt;AWSElasticTranscoder&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Transcriber interface — implemented by an &lt;code class=&quot;language-text&quot;&gt;AWSTranscriber&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2. State changes flow through the aggregate as a saga&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &quot;saga&quot; is a series of local transactions.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A &lt;code class=&quot;language-text&quot;&gt;streamJob&lt;/code&gt; has several of these.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The high-level policy is that our saga goes → &lt;code class=&quot;language-text&quot;&gt;reformatMedia&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;extractAudio&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;combineMedia&lt;/code&gt;. That&apos;s how we complete a streamJob.&lt;/li&gt;
&lt;li&gt;The low-level policy is that, in AWS, all of this work is done in S3 buckets. So when our job is done, we&apos;ll likely want to do some cleanup. A &lt;code class=&quot;language-text&quot;&gt;streamJobCompleted&lt;/code&gt; event could be subscribed to in order to clean up those temporary files in our S3 buckets.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;3. An example use case&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We might realize that the &lt;code class=&quot;language-text&quot;&gt;streamJob&lt;/code&gt; aggregate needs the following properties: &lt;code class=&quot;language-text&quot;&gt;JobState&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;InitialMedia&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;TextFromAudio&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;MediaAudio&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;TranscribedMedia&lt;/code&gt;, etc. These are all domain objects used to get from the beginning to the end of the saga. And they are created as we progress through.&lt;/li&gt;
&lt;li&gt;For example, the &lt;code class=&quot;language-text&quot;&gt;TranscribeAudioUseCase&lt;/code&gt;, which is invoked after a &lt;code class=&quot;language-text&quot;&gt;MediaReformmated&lt;/code&gt; event, might look something like this:&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TranscribeAudioUseCase&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;streamJobId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; streamJob &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;streamJobRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getJobById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;streamJobId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;streamJob&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shouldTranscribe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Not ready to transcribe&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Gets the url of the S3 bucket containing the reformmated media then&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// transcribes it. The streamJob aggregate&apos;s `setTranscribedText()` method&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// is called, updating the state of the aggregate and saving the transcribed text&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// to the streamJob aggregate as well. A &quot;MediaTranscribed&quot; event is created and&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// added to the aggregate.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;awsTranscriber&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;transcribe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;streamJob&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// The aggregate is saved and the &quot;MediaTranscribed&quot; event is dispatched.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;streamJobRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;streamJob&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And here&apos;s a snippet of what that state-changing method might look like.&quot;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;StreamJob&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;StreamJobProps&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;setTranscribedText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;transcription&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Transcription&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; InvalidStateError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MediaReformmated&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InvalidStateError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;transcription &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; transcription&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MediaTranscribed&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDomainEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MediaTranscribed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;Khalil! Thank you for your comprehensive reply. And I noticed I have to learn about saga in DDD. Your example is assuming that we outsource transcription to 3rd-party service. I need to explain my situation in detail. I need to handle logic - such as transcribing, combining, creating files, removing files, etc. - in a pipeline in stream.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-discussion-transcription/stream.png&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A video source is out there.
Video source is generating video chunks continuously.
In my service, the system gets a video chunk from a stream and converts it into a proper audio format.
And sends it to the transcribing service and gets transcripts.
And then the system saves the audio chunk and transcript as files and updates the playlist.
Lastly, the system removes old files that are not necessary anymore.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;I also posted pseudo code for my current implementation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TranscribeAudioUseCase&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;videoSourceUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; videoSourceStream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createVideoSourceStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;videoSoureUrl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    videoSourceStream
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Writable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
           &lt;span class=&quot;token function-variable function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; encoding&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
             &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; converted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;audioConverter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;convert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;converted&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Writable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token function-variable function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; encoding&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; transcript &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;transcriptionService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;transcribe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; transcript&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
         &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Writable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function-variable function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; encoding&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
              &lt;span class=&quot;token comment&quot;&gt;// playlistManager add new audio and transcript files and removes old files&lt;/span&gt;
              &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;playlistManager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
         &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;At this point, I have several questions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;1 - Do you think it&apos;s okay that a &quot;stream&quot; object is exposed to use cases or domain?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;2 - In dealing files on domain, are domain objects allowed to have saved paths or not? For example, if we introduce AudioSegment in the domain layer, is it okay that AudioSegment has a path where it is saved? How can you decide a property is for domain or for infra?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;3 - Sometimes, talking with domain experts is too abstract. I know we should develop that concept in detail and usually I do. But like this case, sometimes domain experts do not know about the concept of stream. And they just say &quot;From this URL, get a video and extract text from it and combine them and show them to me&quot;. I know it is good to use those terms into domain objects. But I think in this case, it depends a lot on what protocol of video source and what protocol we should serve. If we use HLS we should save target duration, sequence number and so on. If we use RTMP we should save values for RTMP packets. I think serving protocols like RTMP, HLS are infra. Thus, they should not corrupt domain or be exposed to domain. But it affects too much what we should put in domain objects.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;Do you think it&apos;s okay that a &quot;stream&quot; object is exposed to use cases or domain?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&quot;The stream is just a functional way to handle logic. There&apos;s probably a way to do this with for or while-loops too. That being said, this approach is elegant and I see no problem with you doing this in the use case. You probably want to be able to promise-ify this and report when it&apos;s complete to the caller (controller, most likely).&lt;/p&gt;
&lt;p&gt;As for making the concept of a stream a part of the domain, you could if that makes sense. You could model a &lt;code class=&quot;language-text&quot;&gt;stream&lt;/code&gt; as a domain object.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In dealing files on domain, domain objects are allowed to have saved paths or not? For example, if we introduce AudioSegment in the domain layer, is it okay that AudioSegment has a path where it is saved?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If it makes sense to the integrity of the domain object, then yes. Again, domain objects can know about technical stuff like file paths, permissions, and such so long as it makes sense to the domain. Your domain is inherently technical. For a userProfile, I&apos;d also save the profilePictureURL as a value prop. Similar situation.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How can you decide a property is for domain or for infra?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I don&apos;t typically have any entities in infrastructure. My infrastructure usually consists of the building blocks on which the application can operate. We&apos;re talking repos, databases, controllers, web servers, adapters to external APIs like Stripe, Google Calendar, etc. &lt;/p&gt;
&lt;p&gt;You said, &quot;protocols like RTMP, HLS are infra&quot;. Protocols like HTTP are typically abstracted away from the domain layer on most of the things I build, but you are building something where the concept of &lt;code class=&quot;language-text&quot;&gt;protocols&lt;/code&gt; are inherent to the domain. The concept of HTTP probably belongs as far away from the domain in a pet store application but it also probably belongs a lot closer if your domain is a file-sharing application, or better yet - a media-streaming application.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sometimes, talking with domain experts is too abstract. I know we should develop that concept in detail and usually, I do. But like this case, sometimes domain experts do not know about the concept of a stream. And they just say &quot;From this URL, get a video and extract text from it and combine them and show them to me&quot;. I know it is good to use those terms in domain objects. But I think in this case, it depends a lot on what protocol of video source and what protocol we should serve. If we use HLS we should save target duration, sequence number and so on. If we use RTMP we should save values for RTMP packets.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yeah, that&apos;s complexity. That&apos;s why we want a domain layer.&lt;/p&gt;
&lt;p&gt;I smell a practical application of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Strategy_pattern&quot;&gt;Strategy Pattern&lt;/a&gt; here. Consider an abstract &lt;code class=&quot;language-text&quot;&gt;StreamProtocol&lt;/code&gt; domain object. It defines the general algorithm necessary for what you need to do to deal with the stream in all cases, but leaves out specific details like handling sequence numbers for HLS or what you should do for RTML.&lt;/p&gt;
&lt;p&gt;This is also the &lt;a href=&quot;https://khalilstemmler.com/articles/solid-principles/solid-typescript/#Open-Closed-Principle&quot;&gt;Open-Closed Principle&lt;/a&gt;. Your &lt;code class=&quot;language-text&quot;&gt;Protocol&lt;/code&gt; object is high-level, and the concrete implementations are low-level. The &lt;code class=&quot;language-text&quot;&gt;Protocol&lt;/code&gt; domain object contains the law. The concrete implementations follow the law, but in their own unique ways. To add support for a new protocol, you merely need to write the new concrete implementation.&quot;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[No title]]></title><description><![CDATA[Entropy Entropy is a fancy word for complexity, randomness, uncertainty or a state of disorder.  Entropy It was first recognized in the…]]></description><link>https://khalilstemmler.com/wiki/coupling-cohesion-connascence/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/coupling-cohesion-connascence/</guid><pubDate>Tue, 09 Feb 2021 04:05:26 GMT</pubDate><content:encoded>&lt;p class=&quot;special-quote&quot;&gt;🌱 This wiki entry hasn&apos;t fully bloomed. It&apos;s very likely to change over the next little while.&lt;/p&gt;
&lt;h2 id=&quot;Entropy&quot; style=&quot;position:relative;&quot;&gt;Entropy&lt;a href=&quot;#Entropy&quot; aria-label=&quot;Entropy permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Entropy is a fancy word for &lt;em&gt;complexity&lt;/em&gt;, &lt;em&gt;randomness&lt;/em&gt;, &lt;em&gt;uncertainty&lt;/em&gt; or &lt;em&gt;a state of disorder&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/wiki/coupling-cohesion-connasence/entropy.svg&quot; alt=&quot;Entropy&quot;&gt;&lt;/p&gt;
&lt;p&gt;It was first recognized in the study of &lt;a href=&quot;https://en.wikipedia.org/wiki/Thermodynamics#Classical_thermodynamics&quot;&gt;thermodynamics&lt;/a&gt; but to us, programmers - &lt;strong&gt;it&apos;s at the heart of everything we&apos;re working to do with software&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Entropy-is-the-real-world&quot; style=&quot;position:relative;&quot;&gt;Entropy is the real world&lt;a href=&quot;#Entropy-is-the-real-world&quot; aria-label=&quot;Entropy is the real world permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We&apos;re in the business of creating things that solve problems for people in the real world. &lt;/p&gt;
&lt;p&gt;And you don&apos;t have to be &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Albert_Camus&quot;&gt;Albert Camus&lt;/a&gt; to realize that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The world &lt;em&gt;is&lt;/em&gt; entropy. It is complex, random, uncertain, and disorderly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The role of software is to cut through that chaos and produce a simplified (or &lt;em&gt;good enough&lt;/em&gt;) model that operates top of that complexity.&lt;/p&gt;
&lt;p&gt;This is hard. This is where all our efforts go.&lt;/p&gt;
&lt;h3 id=&quot;Things-we-do-to-tame-complexity&quot; style=&quot;position:relative;&quot;&gt;Things we do to tame complexity&lt;a href=&quot;#Things-we-do-to-tame-complexity&quot; aria-label=&quot;Things we do to tame complexity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Learn the domain with Agile planning &amp;#x26; discovery practices: If we&apos;re going to get anywhere close to building something useful and maintainable, we better start with learning the language of the domain. Event Storming (or Event Modeling), BDD, user stories to build a shared understanding and map out what we want to build. &lt;/li&gt;
&lt;li&gt;Use Agile technical practices: DDD, BDD, TDD, acceptance tests, pair programming to model the domain, catch regressions, and ensure quick feedback loops.&lt;/li&gt;
&lt;li&gt;Design patterns and principles: SOLID, YAGNI, Simple Design, etc.&lt;/li&gt;
&lt;li&gt;Clean code: Style, formatting, conventions, object calisthenics, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/wiki/coupling-cohesion-connasence/xp_techniques.svg&quot; alt=&quot;XP Techniques&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Agile/XP techniques and processes help us wrangle entropy into acceptance tested features - see &quot;&lt;a target=&quot;_blank&quot; href=&quot;https://wiki.solidbook.io/13-Features-(use-cases)-are-the-key-193ca4bbb8604c0eada33d1ac86ed517&quot;&gt;13. Features (use-cases) are the key&lt;/a&gt;&quot; from &lt;a target=&quot;_blank&quot; href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There is, however, one truly foundational technique we use to solve the complexity problem. It&apos;s one we&apos;ve relied on ever since the early structured programming days. It&apos;s the technique of &lt;em&gt;functional decomposition&lt;/em&gt;: &lt;strong&gt;decomposing the problem into smaller pieces&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Functional decomposition is great but it can have both &lt;em&gt;positive&lt;/em&gt; and &lt;em&gt;negative&lt;/em&gt; impacts coupling &amp;#x26; cohesion: the best measures of structural software quality there is.&lt;/p&gt;
&lt;h2 id=&quot;Coupling&quot; style=&quot;position:relative;&quot;&gt;Coupling&lt;a href=&quot;#Coupling&quot; aria-label=&quot;Coupling permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Coupling is a measure of how intertwined two components (and by components, we mean: routines, methods, functions, classes, modules, etc) are.&lt;/p&gt;
&lt;p&gt;It&apos;s said that we should strive for &lt;strong&gt;loose coupling&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Loose coupling is &lt;em&gt;good&lt;/em&gt; because it works to &lt;strong&gt;reduce maintenance costs by making code more testable and flexible&lt;/strong&gt;. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Loose coupling (ideal)&lt;/strong&gt;: Components are pretty independent and not tied to others. This helps testability and flexibility.&lt;/li&gt;
&lt;li&gt;Tight coupling: Components are inseparable. Changes made to one component in the group will likely ripple into the other dependent components. This hurts maintainability, testability, and flexibility. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/wiki/coupling-cohesion-connasence/entropy-and-coupling.svg&quot; alt=&quot;Entropy and coupling&quot;&gt;&lt;/p&gt;
&lt;!-- TODO: Demonstrate various different ways that coupling can appear --&gt;
&lt;p&gt;It&apos;s not really possible to have &lt;em&gt;zero&lt;/em&gt; coupling because the components we write need to be hooked up to each other in order for our software to do anything meaningful.&lt;/p&gt;
&lt;p&gt;That being said, when things are &lt;em&gt;loosely&lt;/em&gt; coupled, it paradoxically hurts the other metric - cohesion. That is, we can say that loose coupling generally correlates to &lt;strong&gt;low cohesion&lt;/strong&gt; (which is bad).&lt;/p&gt;
&lt;p&gt;What&apos;s cohesion then?&lt;/p&gt;
&lt;h2 id=&quot;Cohesion&quot; style=&quot;position:relative;&quot;&gt;Cohesion&lt;a href=&quot;#Cohesion&quot; aria-label=&quot;Cohesion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Cohesion is a measure of how related components are within a particular module. It&apos;s a measure of how much they &lt;em&gt;belong together&lt;/em&gt;. Do you have stuff in here mostly focused on the topic at hand? Or is there stuff in here that probably belongs elsewhere?&lt;/p&gt;
&lt;p&gt;You want to strive for &lt;strong&gt;high cohesion&lt;/strong&gt;.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Tip&lt;/b&gt;: If you have classes that you call &lt;i&gt;helpers&lt;/i&gt; that does &lt;i&gt;a lot of random different things for many different areas of your code and isn&apos;t quite focused on one particular problem&lt;/i&gt;, it likely means that your cohesion is &lt;i&gt;low&lt;/i&gt;.&lt;p&gt;
&lt;p&gt;Here&apos;s an example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Bad cohesion - not focused on a single responsibility&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;RequestHelpers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;details&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getEmailFromRequest&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;checkForumExists&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;isAuthenticated&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;endTransaction&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

&lt;span class=&quot;token comment&quot;&gt;// Good cohesion&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TextUtil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strip&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isPalindrome&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;replaceAll&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;text&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; replacement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toCamelCase&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;High cohesion is &lt;em&gt;good&lt;/em&gt; because it works to &lt;strong&gt;reduce maintenance costs by making code more understandable&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;High cohesion (ideal)&lt;/strong&gt;: When a component (like a class, for example) has methods that all appear to be related to an underlying concept, then the class is said to have high cohesion. This helps understandability.&lt;/li&gt;
&lt;li&gt;Low cohesion: Many classes with only a single method (that would belong better together) or one class with lots of methods (that aren&apos;t related) is an example of low cohesion.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/wiki/coupling-cohesion-connasence/entropy-and-cohesion.svg&quot; alt=&quot;Entropy and cohesion&quot;&gt;&lt;/p&gt;
&lt;p&gt;The problem with &lt;em&gt;high cohesion&lt;/em&gt; is that it typically correlates to &lt;em&gt;tight coupling&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;What-do-we-do&quot; style=&quot;position:relative;&quot;&gt;What do we do?&lt;a href=&quot;#What-do-we-do&quot; aria-label=&quot;What do we do permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You see the conundrum we&apos;re in?&lt;/p&gt;
&lt;p&gt;We optimize for &lt;em&gt;cohesion&lt;/em&gt; we lose coupling. &lt;/p&gt;
&lt;p&gt;We optimize for &lt;em&gt;coupling&lt;/em&gt; we lose cohesion.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The doctrine of the mean: The most virtuous act is not the extreme - one side or the other. Instead, it&apos;s the &lt;em&gt;middle path&lt;/em&gt;; this is what the &lt;em&gt;best&lt;/em&gt; spot is. ━ Me, paraphrasing Aristotle&apos;s ethics&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It turns out that there&apos;s another mental model we can use to balance dependencies.&lt;/p&gt;
&lt;h2 id=&quot;Connascence&quot; style=&quot;position:relative;&quot;&gt;Connascence&lt;a href=&quot;#Connascence&quot; aria-label=&quot;Connascence permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It&apos;s called &lt;em&gt;connascence&lt;/em&gt;: a &lt;em&gt;generalization&lt;/em&gt; of coupling and cohesion into one &quot;holistic approach&quot; according to &lt;a href=&quot;https://connascence.io/&quot;&gt;connascence.io&lt;/a&gt;. &lt;/p&gt;
&lt;h3 id=&quot;What-is-it&quot; style=&quot;position:relative;&quot;&gt;What is it?&lt;a href=&quot;#What-is-it&quot; aria-label=&quot;What is it permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Also according to &lt;a href=&quot;https://connascence.io/&quot;&gt;connascence.io&lt;/a&gt;, &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Connascence is a metric, and like all metrics, it is an imperfect measure. However, connascence takes a more holistic approach, where each instance of connascence in a codebase must be considered on three separate axes:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ol&gt;
&lt;li&gt;Strength. Stronger connascence is harder to discover or harder to refactor.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Degree. An entity that is connascent with thousands of other entities is likely to be a larger issue than one that is connascent with only a few.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Locality. Connascent elements that are close together in a codebase are better than ones that are far apart.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;The three properties of Strength, Degree, and Locality give the programmer all the tools they need in order to make informed decisions about when they will permit certain types of coupling, and when the code ought to be refactored.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Well &lt;em&gt;that&apos;s&lt;/em&gt; powerful.&lt;/p&gt;
&lt;p&gt;The following image lists the different forms of connascence, ordered by strength.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/wiki/coupling-cohesion-connasence/connascence.svg&quot; alt=&quot;Connascence&quot;&gt;&lt;/p&gt;
&lt;p&gt;You want to prefer refactorings that push you towards the &lt;strong&gt;weaker connascence types&lt;/strong&gt; (when a component is changed, it&apos;s less likely that that change will ripple into another component) over the &lt;em&gt;stronger ones&lt;/em&gt; (more likely to introduce ripple).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/wiki/coupling-cohesion-connasence/entropy-and-connascence.svg&quot; alt=&quot;Entropy and connascence&quot;&gt;&lt;/p&gt;
&lt;p&gt;Apparently this concept goes way back to 1992 when Meilir Page-Jones first introduced it in &quot;&lt;em&gt;Comparing Techniques by Means of Encapsulation and Connascence&lt;/em&gt;&quot;. It was also written about in &lt;a target=&quot;_blank&quot; href=&quot;https://www.amazon.com/Fundamentals-Object-Oriented-Design-Meilir-Page-Jones/dp/020169946X/ref=asap_bc?ie=UTF8&quot;&gt;Fundamentals of Object-Oriented Design in UML&lt;/a&gt; in 1999, and recently expanded on in 2009 in a presentation called &quot;&lt;a href=&quot;https://www.youtube.com/watch?v=NLT7Qcn_PmI&amp;#x26;ab_channel=Confreaks&quot;&gt;The Grand Unified Theory of Software Development&lt;/a&gt;&quot; by Jim Weirich.&lt;/p&gt;
&lt;p&gt;I have more to say about this, but I&apos;m still figuring out the best way to present it. So for now, I&apos;ll recommend you read &lt;a href=&quot;https://connascence.io/&quot;&gt;the official site on the topic and check out the examples&lt;/a&gt;. I&apos;ll update this page at some point.&lt;/p&gt;
&lt;h2 id=&quot;Resources&quot; style=&quot;position:relative;&quot;&gt;Resources&lt;a href=&quot;#Resources&quot; aria-label=&quot;Resources permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://connascence.io/&quot;&gt;https://connascence.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://programhappy.net/2020/06/22/connascence-why-is-it-so-important/&quot;&gt;https://programhappy.net/2020/06/22/connascence-why-is-it-so-important/&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codesai.com/2017/01/about-connascence#nota5&quot;&gt;https://codesai.com/2017/01/about-connascence#nota5&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[No title]]></title><description><![CDATA[ORMs like Sequelize and Prisma use the Active Record pattern which lets you add, remove, delete, and update data from SQL server without…]]></description><link>https://khalilstemmler.com/wiki/leaky-abstraction/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/leaky-abstraction/</guid><pubDate>Tue, 09 Feb 2021 04:05:26 GMT</pubDate><content:encoded>&lt;p class=&quot;special-quote&quot;&gt;🌱 This wiki entry hasn&apos;t fully bloomed. It&apos;s very likely to change over the next little while.&lt;/p&gt;
&lt;p&gt;ORMs like Sequelize and Prisma use the &lt;strong&gt;Active Record&lt;/strong&gt; pattern which lets you add, remove, delete, and update data from SQL server without ever needing to write any SQL code. For simple cases, they work amazingly. They even tend to work pretty well for more non-trivial queries as well. The downside is that when we run into the scenario where we need to use our ORMs to write really complex queries, it&apos;s not uncommon that they plan and execute inefficient SQL code. In situations like this, the abstraction of the ORM has &lt;strong&gt;leaked&lt;/strong&gt;, and we&apos;re forced to either learn how to make the ORM write a more performant query, or to manually write the more efficient SQL query ourselves.&lt;/p&gt;
&lt;h3 id=&quot;The-Law-of-Leaky-Abstractions&quot; style=&quot;position:relative;&quot;&gt;The Law of Leaky Abstractions&lt;a href=&quot;#The-Law-of-Leaky-Abstractions&quot; aria-label=&quot;The Law of Leaky Abstractions permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Joel_Spolsky&quot;&gt;Joel Spolsky&lt;/a&gt;, co-founder of StackOverflow, famously coined the &lt;strong&gt;Law of Leaky Abstractions&lt;/strong&gt; which states:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;All non-trivial abstractions, to some degree, are leaky.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Much of software development is creating abstractions. We write &lt;em&gt;collections&lt;/em&gt; to abstract a list of items. We write value objects to make objects appear as if they&apos;re primitive types. We use the file system API which makes it seem like it&apos;s a structured hierarchy of files and folders. We write RESTful APIs and client libraries to abstract the complexity of interacting with our backend services.&lt;/p&gt;
&lt;p&gt;All &lt;em&gt;non-trivial&lt;/em&gt; abstractions (the more complex ones), to some degree, &lt;strong&gt;leak&lt;/strong&gt;. As in, they leak &lt;em&gt;implementation details&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Examples-in-modern-tooling&quot; style=&quot;position:relative;&quot;&gt;Examples in modern tooling&lt;a href=&quot;#Examples-in-modern-tooling&quot; aria-label=&quot;Examples in modern tooling permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;React.js&lt;/strong&gt; — React is a view layer library that lets you create user interfaces. While the API for React is small and you can get far by following the &lt;strong&gt;rules of React&lt;/strong&gt; (like &lt;em&gt;only put hooks in classes with render functions or other hooks&lt;/em&gt;), it&apos;s not uncommon to run into scenarios where you need to learn more about how React determines when to re-render, when it calls &lt;em&gt;effects&lt;/em&gt; and when components are &lt;em&gt;unmounted&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/wiki/leaky-abstractions/swizec-leaky.png&quot; alt=&quot;Swizec leaky&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Apollo Client — Apollo Client automatically handles the GraphQL data fetching logic and caching logic for you. However, to evict or manipulate data in the cache, you need to learn how it &lt;a href=&quot;https://www.apollographql.com/blog/demystifying-cache-normalization/&quot;&gt;normalizes that cached data&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.djangoproject.com/&quot;&gt;The Django Web Framework&lt;/a&gt; — I swear this is 95% magic.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can probably think of thousands more leaky abstractions. If it&apos;s &lt;strong&gt;non-trivial (meaning, it does something really substantial), then it&apos;s only a matter of time until you run into a leak.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;Should-we-not-use-tools-with-leaky-abstractions&quot; style=&quot;position:relative;&quot;&gt;Should we not use tools with leaky abstractions&lt;em&gt;?&lt;/em&gt;&lt;a href=&quot;#Should-we-not-use-tools-with-leaky-abstractions&quot; aria-label=&quot;Should we not use tools with leaky abstractions permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;No, that&apos;s not the point. Tooling ultimately saves us time. Who wants to go and write another React for the sake of... oh wait. &lt;/p&gt;
&lt;p&gt;Alright, well. The point is to remember &lt;strong&gt;The Law of Leaky Abstractions&lt;/strong&gt;. Keep in mind that &lt;strong&gt;everything non-trivial will eventually leak&lt;/strong&gt;. And when it does, you may have to roll up your sleeves to understand how the abstraction works behind the scenes.&lt;/p&gt;
&lt;p&gt;This can help you make decisions as to what kinds of tools you want to use. &lt;/p&gt;
&lt;p&gt;Don&apos;t believe that &lt;em&gt;anyone&lt;/em&gt; that says their tool can abstract everything away. It&apos;s just a matter of time until you&apos;re forced to learn the internals.&lt;/p&gt;
&lt;h3 id=&quot;How-do-we-apply-this-knowledge-to-our-coding-practices&quot; style=&quot;position:relative;&quot;&gt;How do we apply this knowledge to our coding practices?&lt;a href=&quot;#How-do-we-apply-this-knowledge-to-our-coding-practices&quot; aria-label=&quot;How do we apply this knowledge to our coding practices permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When you&apos;re designing abstractions, you want to make sure that other developers understand how to use them &lt;strong&gt;strictly from the public interface&lt;/strong&gt;. You want to shield others from the complexity behind the scenes of your abstraction.&lt;/p&gt;
&lt;p&gt;But if something doesn&apos;t work correctly, or they can&apos;t figure out how to fit what you wrote for their use case, it&apos;s said to be a leaky abstraction.&lt;/p&gt;
&lt;p&gt;See here for an example.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Bonus (aside)&lt;/b&gt;: Mark Phillips (Supreme Dreams) has a really funny video that almost perfectly demonstrates the idea of a leaky abstraction in real life. &lt;a target=&quot;_blank&quot; href=&quot;https://twitter.com/SupremeDreams_1/status/1294011465259790339&quot;&gt;Check it out&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Related&quot; style=&quot;position:relative;&quot;&gt;Related&lt;a href=&quot;#Related&quot; aria-label=&quot;Related permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/articles/oop-design-principles/maintain-a-single-layer-of-abstraction/&quot;&gt;Maintain a Single Layer of Abstraction at a Time | Object-Oriented Design Principles w/ TypeScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/wiki/coupling-cohesion-connascence&quot;&gt;Coupling, Cohesion &amp;#x26; Connascence | Wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Also-read&quot; style=&quot;position:relative;&quot;&gt;Also read&lt;a href=&quot;#Also-read&quot; aria-label=&quot;Also read permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a target=&quot;_blank&quot; href=&quot;http://danielwaterworth.com/bloglets/2018_02_27&quot;&gt;React is a Leaky Abstraction&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Maintain a Single Layer of Abstraction at a Time | Object-Oriented Design Principles w/ TypeScript]]></title><description><![CDATA[Some people think programming is similar to story-telling. If that's the case, then good code is an incredibly boring and one-dimensional…]]></description><link>https://khalilstemmler.com/articles/oop-design-principles/maintain-a-single-layer-of-abstraction/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/oop-design-principles/maintain-a-single-layer-of-abstraction/</guid><pubDate>Mon, 08 Feb 2021 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Some people think programming is similar to story-telling. If that&apos;s the case, then &lt;strong&gt;good code is an incredibly boring and one-dimensional story&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;Here are two stories.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/design-principles/maintain-a-single/two-stories.png&quot; alt=&quot;Two stories - mixed abstractions&quot;&gt;&lt;/p&gt;
&lt;p&gt;Be honest. Which of those two stories did you finish reading? &lt;strong&gt;The first one, right&lt;/strong&gt;? &lt;/p&gt;
&lt;p&gt;But why? &lt;/p&gt;
&lt;p&gt;Well, the &lt;em&gt;first story&lt;/em&gt; is quick and succinct. We get a birds-eye view of what&apos;s going on, and if we&apos;re curious to know more, we can ask and go a level deeper. The &lt;em&gt;second story&lt;/em&gt; gives us everything. And it&apos;s pretty fatiguing.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;The more complex your system becomes, the more you need to lean on abstractions to keep code readable and maintainable.&lt;/p&gt;
&lt;p&gt;Since much of software development is &lt;strong&gt;reading code&lt;/strong&gt;, using encapsulation and information-hiding to abstract away complexity and lower-level details becomes critical. &lt;/p&gt;
&lt;p&gt;Used correctly, the plus side of this is that we end up with code that&apos;s easier to read, easier to ramp up and learn the domain, and it &lt;em&gt;can&lt;/em&gt; — along with tests, even act as the primary form of documentation.&lt;/p&gt;
&lt;p&gt;Used &lt;em&gt;incorrectly&lt;/em&gt;, or &lt;em&gt;not at all&lt;/em&gt;, we end up with &lt;a href=&quot;/wiki/leaky-abstraction&quot;&gt;leaky abstractions&lt;/a&gt;, poor cohesion, and (since &quot;we&apos;re always building an API&quot;) poor APIs for our fellow teammates and future maintainers to build on top of. &lt;/p&gt;
&lt;p&gt;Therefore, the object-oriented design principle in question is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Maintain a Single Layer of Abstraction at a Time (or &lt;em&gt;in other words,&lt;/em&gt; Don&apos;t Mix Different Levels of Abstractions)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;By maintaining a single layer of abstraction at a time, we write &lt;strong&gt;more&lt;/strong&gt; &lt;strong&gt;cohesive&lt;/strong&gt; and &lt;strong&gt;loosely coupled&lt;/strong&gt; functions, methods, classes, and modules, which in turn improves the &lt;em&gt;readability&lt;/em&gt; and &lt;em&gt;maintainability&lt;/em&gt; of your code.&lt;/p&gt;
&lt;p&gt;Let&apos;s take a closer look at this and how it works.&lt;/p&gt;
&lt;h2 id=&quot;Prerequisite-reading&quot; style=&quot;position:relative;&quot;&gt;Prerequisite reading&lt;a href=&quot;#Prerequisite-reading&quot; aria-label=&quot;Prerequisite reading permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before reading this article, I highly recommend the following. I&apos;ve noted the relevant takeaways from each, but I recommend reading them if you find yourself confused or you don&apos;t find yourself aggressively nodding your head in agreement.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/wiki/coupling-cohesion-connascence&quot;&gt;Coupling, Cohesion &amp;#x26; Connascence&lt;/a&gt; — Entropy (complexity) is at the heart of what makes it hard to write software. To tame complexity, we decompose the problem into smaller parts. But software is only useful when those parts are connected. Coupling and cohesion are the two best measurements of the quality of our decomposition attempts. We should strive for &lt;strong&gt;loose coupling&lt;/strong&gt; and &lt;strong&gt;high cohesion&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;(Abstraction) Layers | Wiki&lt;/strong&gt; — We use layers (domain, application, infrastructure, and adapter) to decompose a web application&apos;s complexity into separate concerns. The introduction of layers means more classes (and evidently, the coupling between layers of classes  — though we can use &lt;a href=&quot;https://khalilstemmler.com/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;Dependency Inversion&lt;/a&gt; to mitigate this). Still, &lt;strong&gt;it can bring the benefit of higher cohesion within classes&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/wiki/leaky-abstraction&quot;&gt;Leaky abstractions&lt;/a&gt; — If we need to know about an object&apos;s internals to use it correctly, depending on the layer of abstraction, we may be leaking implementation details. This leads to &lt;strong&gt;lower cohesion&lt;/strong&gt; and &lt;strong&gt;tighter coupling&lt;/strong&gt; between components.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Another-real-world-example&quot; style=&quot;position:relative;&quot;&gt;Another real-world example&lt;a href=&quot;#Another-real-world-example&quot; aria-label=&quot;Another real world example permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let me walk you through a real-world example.&lt;/p&gt;
&lt;p&gt;Take my initial attempt at a &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use case (application service)&lt;/a&gt; that syncs my Notion Habits dashboard to my Google Calendar.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/syncHabitsToCalendar.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UseCase &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../shared/logic/UseCase&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Calendar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../domain/calendar&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CalendarService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../domain/calendarService&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Habits &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../domain/habit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; googleCalendar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../services&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; GoogleCalendar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../services/googleCalendar&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; HabitsPage &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../services/habitsPage&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SyncHabitsToCalendar&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; habitsPage&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HabitsPage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; googleCalendar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GoogleCalendar&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token parameter&quot;&gt;habitsPage&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HabitsPage&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    googleCalendar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GoogleCalendar&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;habitsPage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; habitsPage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleCalendar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Loading habits... 5 seconds&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;habitsPage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; habits&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Habits &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;habitsPage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAllHabits&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; calendar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Calendar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleCalendar
			&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCalendarForCurrentMonth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; creates&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; updates&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; deletes &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CalendarService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;planSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;habits&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; calendar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;creates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;updates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;u&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;deletes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;d&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;habitsPage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;cleanup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Whats-happening-here&quot; style=&quot;position:relative;&quot;&gt;What&apos;s happening here?&lt;a href=&quot;#Whats-happening-here&quot; aria-label=&quot;Whats happening here permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;habitsPage&lt;/code&gt; is an abstraction over a &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/puppeteer/puppeteer&quot;&gt;Puppeteer&lt;/a&gt; instance that loads and stores habits from my Notion habits page. We then create a &lt;code class=&quot;language-text&quot;&gt;CalendarService&lt;/code&gt; (domain service) by passing in both a &lt;code class=&quot;language-text&quot;&gt;habits&lt;/code&gt; collection and a &lt;code class=&quot;language-text&quot;&gt;calendar&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;We then run a series of &lt;code class=&quot;language-text&quot;&gt;Promise.all&lt;/code&gt; statements, passing the create, update, and delete actions to the correct &lt;code class=&quot;language-text&quot;&gt;googleCalendar&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;Finally, we tell the &lt;code class=&quot;language-text&quot;&gt;habitsPage&lt;/code&gt; to clean up — and by this, we&apos;re really telling the Puppeteer instance to destroy itself to free up resources.&lt;/p&gt;
&lt;h2 id=&quot;Problems&quot; style=&quot;position:relative;&quot;&gt;Problems?&lt;a href=&quot;#Problems&quot; aria-label=&quot;Problems permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are some subtle issues.&lt;/p&gt;
&lt;h3 id=&quot;Application-layer-responsibilities&quot; style=&quot;position:relative;&quot;&gt;Application layer responsibilities&lt;a href=&quot;#Application-layer-responsibilities&quot; aria-label=&quot;Application layer responsibilities permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&apos;s first remember the responsibilities of a use case in the &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/organizing-app-logic/#3-Application-Logic--Use-Cases&quot;&gt;application layer&lt;/a&gt; in a layered (clean, hexagonal, etc.) architecture. Regarding the application layer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It contains the features — the &lt;em&gt;use cases&lt;/em&gt;, of our application&lt;/li&gt;
&lt;li&gt;It is concerned with the rules that govern the application itself. For example, in a pet grooming application, a &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/organizing-app-logic/#Domain-Layer&quot;&gt;domain layer&lt;/a&gt; business rule might state that &lt;strong&gt;a pet must have an owner&lt;/strong&gt;. Such invariants could be enforced within &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/entities/&quot;&gt;entities&lt;/a&gt;, &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-value-object/&quot;&gt;value objects&lt;/a&gt;, and &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;aggregates&lt;/a&gt; within the domain layer. Conversely, an application layer rule might enforce the fact that you can only &lt;strong&gt;edit a grooming appointment&lt;/strong&gt; &lt;strong&gt;if you&apos;re one of many owners of the pet (authorization logic)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt; (one of the main implementation patterns from the application layer) primarily exist to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Retrieve domain objects from IO (using &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;repositories&lt;/a&gt; to databases or adapters to external APIs) so that it orchestrate the execution domain objects&apos; encapsulated business rules and persist any events or state changes they create.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/design-principles/maintain-a-single/application-layer.svg&quot; alt=&quot;Application layer&quot;&gt;&lt;/p&gt;
&lt;p&gt;With that in mind, we can call out a few &lt;em&gt;leaking abstractions&lt;/em&gt; in the first attempt of this design.&lt;/p&gt;
&lt;h3 id=&quot;Problem-1-Leaking-abstraction-Calling-load-on-the-habits-page&quot; style=&quot;position:relative;&quot;&gt;Problem #1: [Leaking abstraction] Calling &lt;code class=&quot;language-text&quot;&gt;load&lt;/code&gt; on the habits page&lt;a href=&quot;#Problem-1-Leaking-abstraction-Calling-load-on-the-habits-page&quot; aria-label=&quot;Problem 1 Leaking abstraction Calling load on the habits page permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Notice that the first thing we do in the &lt;code class=&quot;language-text&quot;&gt;execute&lt;/code&gt; method of the &lt;code class=&quot;language-text&quot;&gt;SyncHabitsToCalendar&lt;/code&gt; use case is to call &lt;code class=&quot;language-text&quot;&gt;load(waitTimeInMilliseconds: number)&lt;/code&gt; on the &lt;code class=&quot;language-text&quot;&gt;habitsPage&lt;/code&gt; object?&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/syncHabitsToCalendar.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SyncHabitsToCalendar&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Loading habits... 5 seconds&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;habitsPage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; habits&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Habits &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;habitsPage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAllHabits&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; calendar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Calendar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleCalendar
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCalendarForCurrentMonth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; creates&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; updates&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; deletes &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CalendarService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;planSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;habits&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; calendar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;creates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;updates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;u&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;deletes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;d&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;habitsPage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;cleanup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Why should the use case need to know that we need to &lt;code class=&quot;language-text&quot;&gt;load&lt;/code&gt; the &lt;code class=&quot;language-text&quot;&gt;habitsPage&lt;/code&gt; before fetching something from it? If we didn&apos;t call &lt;code class=&quot;language-text&quot;&gt;load&lt;/code&gt; and instead just called &lt;code class=&quot;language-text&quot;&gt;getAllHabits&lt;/code&gt;, what would happen? &lt;/p&gt;
&lt;p&gt;We&apos;d always get an empty list back. Behind that &lt;code class=&quot;language-text&quot;&gt;load&lt;/code&gt; method is the process of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;starting up a puppeteer browser instance&lt;/li&gt;
&lt;li&gt;going to the page to load the habits&lt;/li&gt;
&lt;li&gt;using cheerio.js to scrape the habits and parse them into domain objects&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Needing to call &lt;code class=&quot;language-text&quot;&gt;load&lt;/code&gt; before we can call &lt;code class=&quot;language-text&quot;&gt;getAllHabits&lt;/code&gt; is an example of a &lt;a href=&quot;/wiki/leaky-abstraction&quot;&gt;leaky abstraction&lt;/a&gt;. We &lt;em&gt;appear&lt;/em&gt; to abstract away the complex details of getting all the habits from my Notion page. Instead, we&apos;ve shifted the knowledge required to utilize this object&apos;s API onto the user (which, in the real world, could be a coworker or a future maintainer). That&apos;s not great. &lt;/p&gt;
&lt;p&gt;A leaky abstraction like this can lead to a lot of bugs, and evidently — frustration. &lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Bonus (aside)&lt;/b&gt;: Mark Phillips (Supreme Dreams) has a really funny video that almost perfectly demonstrates the idea of a leaky abstraction in real life. &lt;a target=&quot;_blank&quot; href=&quot;https://twitter.com/SupremeDreams_1/status/1294011465259790339&quot;&gt;Check it out&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To fix this problem, we could relocate the logic to a better place: inside the &lt;code class=&quot;language-text&quot;&gt;HabitsPage&lt;/code&gt; class. Here, we encapsulate knowing when to call &lt;code class=&quot;language-text&quot;&gt;load&lt;/code&gt; in &lt;code class=&quot;language-text&quot;&gt;HabitsPage&lt;/code&gt; with the following:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;services/HabitsPage.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HabitsPage&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getAllHabits&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Habits&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;	  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasLoadedHabits&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;	    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;	  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;	
	  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;habits&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Client usage in the use case looks like this now:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/syncHabitsToCalendar.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SyncHabitsToCalendar&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; habits&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Habits &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;habitsPage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAllHabits&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; calendar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Calendar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleCalendar
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCalendarForCurrentMonth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; creates&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; updates&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; deletes &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CalendarService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;planSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;habits&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; calendar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;creates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;updates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;u&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;deletes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;d&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;habitsPage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;cleanup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Much better. Moving on.&lt;/p&gt;
&lt;h3 id=&quot;Problem-2-Mixed-levels-of-abstraction-Theres-persistence-logic-in-our-use-case&quot; style=&quot;position:relative;&quot;&gt;Problem #2: [Mixed levels of abstraction] There&apos;s persistence logic in our use case!&lt;a href=&quot;#Problem-2-Mixed-levels-of-abstraction-Theres-persistence-logic-in-our-use-case&quot; aria-label=&quot;Problem 2 Mixed levels of abstraction Theres persistence logic in our use case permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The next thing that needs attention is the fact that we&apos;ve put &lt;em&gt;persistence logic&lt;/em&gt; in our use case. &lt;/p&gt;
&lt;p&gt;As a reminder, use cases are only supposed &lt;strong&gt;coordinate the interaction between objects&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/syncHabitsToCalendar.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SyncHabitsToCalendar&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; habits&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Habits &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;habitsPage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAllHabits&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; calendar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Calendar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleCalendar
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCalendarForCurrentMonth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; creates&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; updates&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; deletes &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CalendarService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;planSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;habits&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; calendar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;creates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;updates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;u&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;deletes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;d&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;habitsPage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;cleanup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This isn&apos;t the &lt;em&gt;worst&lt;/em&gt; thing. Typically when we want to save entities to a repository, we merely pass the new entity off to a &lt;code class=&quot;language-text&quot;&gt;save&lt;/code&gt; method, which does all the hard work behind the scenes.&lt;/p&gt;
&lt;p&gt;However, our current implementation could be a little more &lt;strong&gt;cohesive&lt;/strong&gt;. This is a bit of a detour from what we should be doing here. It also &lt;strong&gt;couples&lt;/strong&gt; our use case to the persistence implementation details (run &lt;em&gt;create&lt;/em&gt; first, then &lt;em&gt;update&lt;/em&gt;, then &lt;em&gt;delete —&lt;/em&gt; perhaps the sequence is important persistence logic). This could make testing this use case more complex.&lt;/p&gt;
&lt;p&gt;Instead of decomposing the &lt;code class=&quot;language-text&quot;&gt;syncPlan&lt;/code&gt; that comes back from the &lt;code class=&quot;language-text&quot;&gt;planSync&lt;/code&gt; method, let&apos;s pass this off to a new object. The new object will contain the knowledge necessary for taking the &lt;code class=&quot;language-text&quot;&gt;syncPlan&lt;/code&gt; and running the persistence strategy.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/syncHabitsToCalendar.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UseCase &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../shared/logic/UseCase&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Calendar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../domain/calendar&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CalendarService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../domain/calendarService&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Habits &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../domain/habit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; googleCalendar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../services&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; GoogleCalendar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../services/googleCalendar&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; HabitsPage &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../services/habitsPage&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; SyncService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../services/syncService&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SyncHabitsToCalendar&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; habitsPage&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HabitsPage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; googleCalendar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GoogleCalendar&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token parameter&quot;&gt;habitsPage&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HabitsPage&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    googleCalendar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GoogleCalendar&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;habitsPage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; habitsPage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleCalendar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; habits&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Habits &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;habitsPage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAllHabits&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; calendar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Calendar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleCalendar
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getRecurringEventsCalendar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; syncPlan &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CalendarService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;planSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;habits&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; calendar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; syncService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SyncService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; syncService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;syncPlan&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;habitsPage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;cleanup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token plain-text&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The story in our &lt;code class=&quot;language-text&quot;&gt;SyncHabitsToCalendar&lt;/code&gt; use case is looking a lot more cohesive now.&lt;/p&gt;
&lt;p&gt;Not only that, but once I moved the logic to this new object, I realized that there was a performance issue. Google was rate-limiting my API calls. I&apos;d need to add some delay between each operation I run. More complexity started peeking its head out at me. Luckily, we encapsulated this complexity within a new domain service.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;services/syncService.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; LogicUtils &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../../shared/utils/LogicUtils&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; SyncPlan &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../domain/calendarService&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; GoogleCalendar &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./googleCalendar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SyncService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; googleCalendar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GoogleCalendar&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token parameter&quot;&gt;googleCalendar&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GoogleCalendar&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleCalendar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeSyncActions&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    milliseconds&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    elements&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    func&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Function&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; element &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; elements&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; =&gt; On action &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;index&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; of &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;elements&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos; =&gt; Waiting&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; milliseconds &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;seconds first...&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; LogicUtils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;milliseconds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
        &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos; =&gt; Executing action...&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos; =&gt; Done&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; index &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hiccup executing action&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; func&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;

  public async sync (syncPlan: SyncPlan): Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; creates&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; updates&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; deletes &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; syncPlan

    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Creating &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;creates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; events.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeSyncActions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; creates&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Updating &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;updates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; events.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeSyncActions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; updates&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Deleting &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;deletes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; events.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeSyncActions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; deletes&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleCalendar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Problem-3-Leaking-abstraction-Cleaning-up-the-habits-page&quot; style=&quot;position:relative;&quot;&gt;Problem #3: [Leaking abstraction] Cleaning up the habits page&lt;a href=&quot;#Problem-3-Leaking-abstraction-Cleaning-up-the-habits-page&quot; aria-label=&quot;Problem 3 Leaking abstraction Cleaning up the habits page permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There was one final thing I considered doing to improve the design. And that&apos;s to make it so that the use case doesn&apos;t know that it needs to call &lt;code class=&quot;language-text&quot;&gt;cleanup&lt;/code&gt; on the &lt;code class=&quot;language-text&quot;&gt;habitsPage&lt;/code&gt; after we&apos;ve finished the sync.&lt;/p&gt;
&lt;p&gt;Why? &lt;strong&gt;It could lead to memory issues if someone created a new use case involving this object and forgot to call &lt;code class=&quot;language-text&quot;&gt;cleanup&lt;/code&gt; at the end.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I haven&apos;t come up with a great approach yet — perhaps we could ensure that the encapsulated browser instance is a &lt;strong&gt;singleton&lt;/strong&gt;. That way, we&apos;d never have more than one instance of it running.&lt;/p&gt;
&lt;p&gt;In the end, I&apos;ve decided that I&apos;m OK with this statement living in the use case.&lt;/p&gt;
&lt;p&gt;Again, &lt;strong&gt;we&apos;re always building APIs for other developers&lt;/strong&gt;, and at the moment, this is going to be one piece of knowledge within the abstraction that will become necessary for others to know about if they&apos;re to use the &lt;code class=&quot;language-text&quot;&gt;habitsPage&lt;/code&gt; API. I&apos;ll think about improving that later.&lt;/p&gt;
&lt;h2 id=&quot;Summary&quot; style=&quot;position:relative;&quot;&gt;Summary&lt;a href=&quot;#Summary&quot; aria-label=&quot;Summary permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&apos;s a summary of the objects involved in this use case, which abstraction layer they belong to, and what their responsibilities are.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/design-principles/maintain-a-single/Mixing_Levels_of_Abstraction.svg&quot; alt=&quot;Mixing levels of abstraction&quot;&gt;&lt;/p&gt;
&lt;p&gt;The important takeaways here are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Write &lt;strong&gt;more cohesive&lt;/strong&gt; code by maintaining a single level of abstraction at a time.&lt;/li&gt;
&lt;li&gt;Know which layer you&apos;re working in and the responsibilities of that layer.&lt;/li&gt;
&lt;li&gt;Learn implementation patterns (like value objects, repos, domain services, etc) and which layer they belong to.&lt;/li&gt;
&lt;li&gt;Remember that you&apos;re always building an API for other developers. Assume that someone else is going to have to know how to use the objects you design. Make the public interfaces foolproof.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Bonus-exercise-Refactoring-a-controller&quot; style=&quot;position:relative;&quot;&gt;Bonus exercise: Refactoring a controller&lt;a href=&quot;#Bonus-exercise-Refactoring-a-controller&quot; aria-label=&quot;Bonus exercise Refactoring a controller permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Given what we&apos;ve just learned, take a look at this controller. &lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;infra/userController.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; db&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; DbConnection&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;db&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; DbConnection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; db&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	
	&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    req&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
	  res&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;response
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;CreateUserHTTPResult&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; body &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// Request validation&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;username &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;email &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clientError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Username, email, or password not provided.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
    
    &lt;span class=&quot;token comment&quot;&gt;// Entity/value validation&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isUsernameValid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; username&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;hasOnlyBasicChars&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;username&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isPasswordValid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; password&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validatePassword&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isEmailValid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isValidEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isUsernameValid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clientError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Username not valid&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isPasswordValid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clientError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Password not valid&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isEmailValid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clientError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Email not valid&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// App logic&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; existingUsernameUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; username &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;existingUsernameUser&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;conflict&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;User already has that username&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; existingEmailUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; email &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;existingEmailUser&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;conflict&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Account already exists! Sign in.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      password&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      emailVerificationState&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;INITIAL&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Successfully created new user&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;

}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;How would you improve this? Remember that a controller is a part of the &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/organizing-app-logic/#2-Data-Access--Adapter-Logic&quot;&gt;infrastructure layer&lt;/a&gt;. What are controller concerns and what are concerns that likely belong elsewhere?&lt;/p&gt;
&lt;h2 id=&quot;Also-related&quot; style=&quot;position:relative;&quot;&gt;Also related&lt;a href=&quot;#Also-related&quot; aria-label=&quot;Also related permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Separation of Concerns&lt;/strong&gt; - The introduction of abstraction layers is an exercise of the separation of concerns design principle. It&apos;s a way to introduce loose coupling between modules.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Outside-in TDD&lt;/strong&gt; — Outside-in TDD (Mockist, London-style) is a more exploratory way to perform TDD that involves starting at the top of the system&apos;s boundary (like a controller or a use case) and gradually building an understanding of how things &lt;em&gt;can work&lt;/em&gt; before committing to building out concrete implementations of classes. I think this topic is related because you can write the public APIs of classes before they exist, designing abstractions in the most human-friendly way possible (while mocking out collaborators for the time being).&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[5 Ways to Manage Lambda Cold Starts]]></title><description><![CDATA[In this article, you will learn how cold start issues occur, what factors contribute to cold starts, and how to manage Lambda cold starts…]]></description><link>https://khalilstemmler.com/blogs/serverless/5-ways-to-manage-lambda-cold-starts/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/serverless/5-ways-to-manage-lambda-cold-starts/</guid><pubDate>Sat, 27 Jun 2020 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;In this article, you will learn how cold start issues occur, what factors contribute to cold starts, and how to manage Lambda cold starts.&lt;/p&gt;
&lt;h2 id=&quot;Understanding-the-Cold-Start-Problem&quot; style=&quot;position:relative;&quot;&gt;Understanding the Cold Start Problem&lt;a href=&quot;#Understanding-the-Cold-Start-Problem&quot; aria-label=&quot;Understanding the Cold Start Problem permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A Lambda cold start occurs when a new function instance must be created and initialized. The cold start refers to the delay between invocation and runtime created by the initialization process. &lt;/p&gt;
&lt;p&gt;Lambda cold starts occur when there is no available function instance to respond to an invocation. This can happen when instances have expired due to inactivity or when there are more invocations than active instances. Cold starts are an inherent problem with &lt;a href=&quot;https://hackernoon.com/what-is-serverless-architecture-what-are-its-pros-and-cons-cc4b804022e9&quot;&gt;serverless models&lt;/a&gt; because providers are unwilling or unable to keep inactive instances alive indefinitely. &lt;/p&gt;
&lt;p&gt;To maximize resource use and optimize provider costs, instances are only kept alive for a set amount of idle time. This means that unless your functions are consistently activated, you are going to have to manage latency caused by cold starts. &lt;/p&gt;
&lt;h2 id=&quot;What-Factors-Contribute-to-Cold-Starts&quot; style=&quot;position:relative;&quot;&gt;What Factors Contribute to Cold Starts?&lt;a href=&quot;#What-Factors-Contribute-to-Cold-Starts&quot; aria-label=&quot;What Factors Contribute to Cold Starts permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Several factors contribute to cold starts when using Lambda functions. While one of these factors is not controllable (i.e. how long AWS keeps instances alive), most are. Below are some of the factors with the greatest impact that you should be mindful of. &lt;/p&gt;
&lt;h3 id=&quot;Languages&quot; style=&quot;position:relative;&quot;&gt;Languages&lt;a href=&quot;#Languages&quot; aria-label=&quot;Languages permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The length of time it takes to cold start an instance depends significantly on the language you use for your function. For example, JavaScript or Python functions will initialize much faster than C# or Java-based ones. &lt;/p&gt;
&lt;p&gt;Additionally, just-in-time (JIT) compilation, like that used by .NET languages, substantially increases start time. This is because the language’s machine agnostic assemblies must be converted to machine-specific assemblies at initialization. &lt;/p&gt;
&lt;h3 id=&quot;Function-chains&quot; style=&quot;position:relative;&quot;&gt;Function chains&lt;a href=&quot;#Function-chains&quot; aria-label=&quot;Function chains permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In many applications, developers use chains of functions to perform tasks. This chaining is fine when functions are already available but can cause significant overhead if not. When chaining, each function in the chain must wait for the possible initialization and response of any later functions. &lt;/p&gt;
&lt;p&gt;This ordered process compounds cold start times and can cause &lt;a href=&quot;https://lumigo.io/blog/aws-lambda-timeout-best-practices/&quot;&gt;Lambda functions to time out&lt;/a&gt;. If timeouts occur, you have to start the invocation process all over, creating even more latency.&lt;/p&gt;
&lt;h3 id=&quot;Virtual-Private-Clouds-VPC&quot; style=&quot;position:relative;&quot;&gt;Virtual Private Clouds (VPC)&lt;a href=&quot;#Virtual-Private-Clouds-VPC&quot; aria-label=&quot;Virtual Private Clouds VPC permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;While VPCs can help keep your data more secure, these networks are a barrier to the performance of Lambda functions. This is because most Lambda functions require an external connection for request and response operations. This connectivity requires the creation of an elastic network interface (ENI).&lt;/p&gt;
&lt;p&gt;When instances are initialized inside a VPC, the cold start process is extended by the creation of the ENI. During this process, an IP must be allocated and the interface attached to the function. Lambda can take up to 10 seconds to complete this process. &lt;/p&gt;
&lt;h2 id=&quot;How-to-Manage-Lambda-Cold-Starts&quot; style=&quot;position:relative;&quot;&gt;How to Manage Lambda Cold Starts&lt;a href=&quot;#How-to-Manage-Lambda-Cold-Starts&quot; aria-label=&quot;How to Manage Lambda Cold Starts permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While you cannot completely eliminate the chance of cold starts when using Lambda you can decrease the impact. When configuring your functions, consider the following tips. &lt;/p&gt;
&lt;h3 id=&quot;1-Measure-current-performance&quot; style=&quot;position:relative;&quot;&gt;1. Measure current performance&lt;a href=&quot;#1-Measure-current-performance&quot; aria-label=&quot;1 Measure current performance permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Measuring the current performance of your configurations can help you identify where you need to make changes and can help you anticipate latency. In particular, you should evaluate how frequently your functions are being invoked, how many invocations occur at once, and how long invocations take. You can then use these values to determine how many dedicated instances you need.&lt;/p&gt;
&lt;p&gt;Performance can be measured directly using metrics sent to &lt;a href=&quot;https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/RunLambdaSchedule.html&quot;&gt;AWS CloudWatch&lt;/a&gt; or you can use third-party tools. The former works well for individual functions but can only provide limited information and is not easily searchable. The latter enables you to invoke your functions many times, can provide visualizations of the results, and enables you to more easily evaluate aggregate data.&lt;/p&gt;
&lt;h3 id=&quot;2-Keep-your-functions-warm&quot; style=&quot;position:relative;&quot;&gt;2. Keep your functions warm&lt;a href=&quot;#2-Keep-your-functions-warm&quot; aria-label=&quot;2 Keep your functions warm permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once your instances are initialized, you can keep them active to avoid the majority of your cold starts. Keeping functions warm can be done by either invoking the function or using warming logic with handler functions. Warmer logic pings functions to check their status, keeping the instance alive even if it isn’t fully invoked. &lt;/p&gt;
&lt;p&gt;To accomplish this, you can either manually configure your logic or you can use tooling to automate the process for many instances. Manual setup involves inserting logic into your handler functions and triggering that logic with CloudWatch Events and cron jobs. Or, with tooling, you can reuse the same logic for concurrent instances. &lt;/p&gt;
&lt;h3 id=&quot;3-Choose-the-right-memory-settings&quot; style=&quot;position:relative;&quot;&gt;3. Choose the right memory settings&lt;a href=&quot;#3-Choose-the-right-memory-settings&quot; aria-label=&quot;3 Choose the right memory settings permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When using Lambda, your memory and &lt;a href=&quot;https://dev.to/byrro/how-to-optimize-lambda-memory-and-cpu-4dj1&quot;&gt;CPU resources&lt;/a&gt; are directly tied. The more memory you provision, the more processing power your functions can access, and the faster initialization can occur. While you may be tempted to keep memory resources low to save costs, doing so can increase your cold start and runtimes times and end up costing you more regardless. &lt;/p&gt;
&lt;p&gt;To avoid higher costs due to insufficient resources, you need to find the balance point between resources and latency. This requires understanding how frequently your functions are invoked, the revenue dependent on those functions, and the latency during cold start and warm invocations.&lt;/p&gt;
&lt;h3 id=&quot;4-Store-dependencies-external-to-your-function&quot; style=&quot;position:relative;&quot;&gt;4. Store dependencies external to your function&lt;a href=&quot;#4-Store-dependencies-external-to-your-function&quot; aria-label=&quot;4 Store dependencies external to your function permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;With Lambda, you can load dependencies into your function container external to your function. This enables you to prep dependencies for invocations and prevents functions from needing to load dependencies each time the instance is called. &lt;/p&gt;
&lt;p&gt;While this process won’t reduce your cold start time, you can use it to reduce your runtimes and offset initial latency. When you use this method in combination with function warming, you can significantly reduce your function runtimes. &lt;/p&gt;
&lt;h3 id=&quot;5-Keep-your-function-small-and-single-purpose&quot; style=&quot;position:relative;&quot;&gt;5. Keep your function small and single-purpose&lt;a href=&quot;#5-Keep-your-function-small-and-single-purpose&quot; aria-label=&quot;5 Keep your function small and single purpose permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Keeping your functions small and single-purpose helps ensure that functions execute quickly and reduces the chances of timeout. It can also reduce the total number of instances you need, thus reducing the chance of cold starts. &lt;/p&gt;
&lt;p&gt;When function invocations finish quickly, that instance is sent back to your available pool. The more available instances in your pool at any given point, the lower the chance that you need to create a new instance to answer an invocation request. Ensuring that functions execute efficiently is a way of “increasing” your pool without requiring more instances. &lt;/p&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A Lambda cold start occurs when function instances are not available to respond to invocations. There are several factors contributing to this issue. The language you use, for example, impacts the length of time it can take to cold start an instance. If you are using function chains, the order of the functions can cause timeouts. If you are planning on setting up your Lambda on VPC, you need to be aware that the process of initializing Lambda functions on VPCs can take up to 10 seconds. &lt;/p&gt;
&lt;p&gt;Unfortunately, you can’t completely eliminate cold starts, but you can significantly reduce the impact this issue may cause. You can do that by measuring current performance and keeping your functions warm, small, and single-purposed. You can also store dependencies externally, and make an effort to choose the right memory settings for your project.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[IV. Conclusion]]></title><description><![CDATA[This is page four of a guide on Client-Side Architecture basics. Start at page one. The work isn't over I know this article expressed a lot…]]></description><link>https://khalilstemmler.com/articles/client-side-architecture/conclusion/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/client-side-architecture/conclusion/</guid><pubDate>Wed, 24 Jun 2020 15:04:10 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;This is page four of a guide on Client-Side Architecture basics. Start at &lt;a href=&quot;/articles/client-side-architecture/introduction&quot;&gt;page one&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;The-work-isnt-over&quot; style=&quot;position:relative;&quot;&gt;The work isn&apos;t over&lt;a href=&quot;#The-work-isnt-over&quot; aria-label=&quot;The work isnt over permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I know this article expressed a lot of new ideas. To be completely honest, I spent about three months thinking about this off and on, and I&apos;m likely going to spend some time revising it and trying these ideas out with real-world projects. &lt;/p&gt;
&lt;p&gt;Stay tuned for updates on this. If you &lt;a href=&quot;/newsletter&quot;&gt;subscribe to the newsletter&lt;/a&gt;, I&apos;ll let you know when I publish major updates.&lt;/p&gt;
&lt;p&gt;Let&apos;s look at what we&apos;ve covered. &lt;/p&gt;
&lt;h2 id=&quot;A-new-client-side-development-philosophy&quot; style=&quot;position:relative;&quot;&gt;A new client-side development philosophy&lt;a href=&quot;#A-new-client-side-development-philosophy&quot; aria-label=&quot;A new client side development philosophy permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Zooming out, we started with this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/model-view-presenter.png&quot; alt=&quot;img/blog/client-side-architecture/Untitled.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;And then zooming in, we landed on this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Client-side_architecture_basics_(5).png&quot; alt=&quot;img/blog/client-side-architecture/Client-side_architecture_basics_(5).png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s recap the statements I&apos;ve made.&lt;/p&gt;
&lt;h4 id=&quot;Model-View-Presenter-isnt-good-enough-for-our-needs-anymore&quot; style=&quot;position:relative;&quot;&gt;Model-View-Presenter isn&apos;t good enough for our needs anymore&lt;a href=&quot;#Model-View-Presenter-isnt-good-enough-for-our-needs-anymore&quot; aria-label=&quot;Model View Presenter isnt good enough for our needs anymore permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The problems we&apos;re solving on the client-side are much more complex than they were 20 years ago. Because of that, the starting point for an architecture probably can&apos;t be MVP.&lt;/p&gt;
&lt;h4 id=&quot;Design-principles-have-persisted-for-a-long-time-to-help-us-write-better-software&quot; style=&quot;position:relative;&quot;&gt;Design principles have persisted for a long time to help us write better software&lt;a href=&quot;#Design-principles-have-persisted-for-a-long-time-to-help-us-write-better-software&quot; aria-label=&quot;Design principles have persisted for a long time to help us write better software permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;I honestly think that reading books and learning from the past is one of the best ways to avoid future mistakes. Design principles are great. You don&apos;t need to always follow them, but know the rules before deciding whether you want to break &apos;em.&lt;/p&gt;
&lt;h4 id=&quot;There-are-no-silver-bullets&quot; style=&quot;position:relative;&quot;&gt;There are no silver bullets&lt;a href=&quot;#There-are-no-silver-bullets&quot; aria-label=&quot;There are no silver bullets permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;There really aren&apos;t. With this advanced client-side architecture, what we introduce in structural quality, we lose in developer experience based on the potential learning curve involved. But ask yourself this question: &lt;a href=&quot;https://khalilstemmler.com/articles/software-professionalism/accidental-and-essential-complexity/&quot;&gt;is the complexity related to nature of the problem itself, or is it just related to the way we&apos;re solving it&lt;/a&gt;?&lt;/p&gt;
&lt;h4 id=&quot;This-is-for-developers-where-use-what-works-for-you-is-daunting-and-would-like-a-good-conceptual-starting-point-for-an-air-tight-React-architecture&quot; style=&quot;position:relative;&quot;&gt;This is for developers where &quot;use what works for you&quot; is daunting, and would like a good conceptual starting point for an air tight React architecture&lt;a href=&quot;#This-is-for-developers-where-use-what-works-for-you-is-daunting-and-would-like-a-good-conceptual-starting-point-for-an-air-tight-React-architecture&quot; aria-label=&quot;This is for developers where use what works for you is daunting and would like a good conceptual starting point for an air tight React architecture permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;I&apos;m really excited about these ideas. I&apos;ve been milling around with this for a couple of months now but I think it&apos;s really important today. If you&apos;re a developer that has been told to use &quot;what works for you&quot;, that&apos;s still incredibly good advice. But if you run into any of the pain-points in your React project like suddenly facing issues adding features, changing code, and feeling like things have turned to mush, this might help.&lt;/p&gt;
&lt;h2 id=&quot;Next-steps&quot; style=&quot;position:relative;&quot;&gt;Next steps&lt;a href=&quot;#Next-steps&quot; aria-label=&quot;Next steps permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p class=&quot;special-quote&quot;&gt;We shouldn&apos;t stop here. Here are a few thoughts to chew on. Feel free to ask questions and leave suggestions on ways I can make this guide more helpful.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Choosing a stack&lt;/strong&gt;: Given this philosophy, what factors into deciding upon a stack? Compatibility? Developer experience? Maintainer(s) activity?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Organizing code:&lt;/strong&gt; How do you organize code within a React project? What principles are at play?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dealing with prop drilling&lt;/strong&gt;: If we have these clear-cut layers, doesn&apos;t that mean we&apos;ll have to do a lot of prop drilling? &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Test-Driven Development&lt;/strong&gt;: Can we discuss testing in more detail? What does a test-driven approach to client-side application development look like in 2020? Should we write BDD-style acceptance tests with React Testing Library and Jest? Or should invest into testing for functional correctness using E2E tools like Cypress.io?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Real-life project&lt;/strong&gt;: What does this look like in practice?&lt;/p&gt;</content:encoded></item><item><title><![CDATA[I. Architecture]]></title><description><![CDATA[This is page one of a guide on Client-Side Architecture basics. Why we need a client-side architecture standard Allow me to paint the…]]></description><link>https://khalilstemmler.com/articles/client-side-architecture/architecture/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/client-side-architecture/architecture/</guid><pubDate>Wed, 24 Jun 2020 15:04:10 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;This is page one of a guide on Client-Side Architecture basics.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;Why-we-need-a-client-side-architecture-standard&quot; style=&quot;position:relative;&quot;&gt;Why we need a client-side architecture standard&lt;a href=&quot;#Why-we-need-a-client-side-architecture-standard&quot; aria-label=&quot;Why we need a client side architecture standard permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Allow me to paint the picture of why we need a better client-side architecture. To start, let&apos;s look at the foundation we&apos;re all currently working on top of.&lt;/p&gt;
&lt;h3 id=&quot;Model-View-controller&quot; style=&quot;position:relative;&quot;&gt;Model-View controller&lt;a href=&quot;#Model-View-controller&quot; aria-label=&quot;Model View controller permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You&apos;ve probably heard of &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller&quot;&gt;Model-View-Controller&lt;/a&gt;&lt;/strong&gt;, the architectural pattern that describes how to design apps involving user interfaces.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MVC&lt;/strong&gt; says that we should split our application into &lt;em&gt;model&lt;/em&gt;, &lt;em&gt;view&lt;/em&gt;, and &lt;em&gt;controller&lt;/em&gt; layers. This is so each layer can focus on their own respective responsibilities. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The model handles data and logic&lt;/li&gt;
&lt;li&gt;The view handles presentation&lt;/li&gt;
&lt;li&gt;and the controller turns user events into changes to the model&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Untitled.png&quot; alt=&quot;img/blog/client-side-architecture/Untitled.png&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Model-view-controller architectural pattern. Used to separate the concerns between a client-side web app and backend services.&lt;/p&gt;
&lt;p&gt;Most full-stack apps are comprised of a &lt;strong&gt;client-side portion,&lt;/strong&gt; utterly separate from &lt;strong&gt;backend services&lt;/strong&gt;. When users ask to make a change from the UI, it makes things happen by interacting with the backend through some API: in MVC, the API is the &lt;em&gt;controller&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This works! And we like it. At least, we &lt;em&gt;must&lt;/em&gt; — it&apos;s one of the first architectural patterns we teach to new developers learning how to build full-stack apps.&lt;/p&gt;
&lt;h3 id=&quot;Model-View-presenter&quot; style=&quot;position:relative;&quot;&gt;Model-View presenter&lt;a href=&quot;#Model-View-presenter&quot; aria-label=&quot;Model View presenter permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Where &lt;em&gt;Model-View-Controller&lt;/em&gt; explained how to separate the concerns of a &lt;strong&gt;full-stack web application&lt;/strong&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter&quot;&gt;Model-View Presenter&lt;/a&gt;, a derivation of MVC, told us how to separate the concerns of &lt;strong&gt;the client part&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/model-view-presenter.png&quot; alt=&quot;Model-View-Presenter&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Model-View-Presenter is the architectural pattern typically used within client applications. It&apos;s a derivation of the MVC pattern.&lt;/p&gt;
&lt;p&gt;In &lt;em&gt;Model-View-Presenter&lt;/em&gt;, the &lt;strong&gt;view&lt;/strong&gt; creates user events. &lt;/p&gt;
&lt;p&gt;Those user events get turned into &lt;strong&gt;updates&lt;/strong&gt; or &lt;strong&gt;changes&lt;/strong&gt; to the model. &lt;/p&gt;
&lt;p&gt;When the &lt;strong&gt;model&lt;/strong&gt; changes, the &lt;strong&gt;view&lt;/strong&gt; is updated with the new data.&lt;/p&gt;
&lt;p&gt;It&apos;s heartening to realize that &lt;b&gt;every client app uses some form of the model-view presenter pattern&lt;/b&gt;.&lt;/p&gt;
&lt;!-- TODO: Add this --&gt;
&lt;!-- &lt;p class=&quot;special-quote&quot;&gt;Additionally, astute developers might notice this is a fancy way to say &lt;i&gt;Observer pattern&lt;/i&gt;. It turns out that &lt;a href=&quot;/articles/client-side-architecture/observer-pattern/&quot;&gt;most client apps are built around the Observer Pattern&lt;/a&gt;. Hold some data, subscribe to it from elsewhere, then notify subscribers when it changes. Each framework/library (React, Vue, Angular) implements this pattern in a slightly different way.&lt;/p&gt; --&gt;
&lt;h3 id=&quot;MVC--MVP-are-too-generic&quot; style=&quot;position:relative;&quot;&gt;MVC &amp;#x26; MVP are too generic&lt;a href=&quot;#MVC--MVP-are-too-generic&quot; aria-label=&quot;MVC  MVP are too generic permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MVC and MVP are great starters. They give you a &lt;em&gt;good enough&lt;/em&gt; understanding of the communication pathways from a 5000-ft view. &lt;/p&gt;
&lt;p&gt;Unfortunately, they both suffer from the same problem: being &lt;em&gt;too generic&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In both MVC and MVP, &lt;strong&gt;the biggest challenge is that the &lt;code class=&quot;language-text&quot;&gt;M&lt;/code&gt; is responsible for way too much&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;As a result, developers don&apos;t know &lt;em&gt;which tools&lt;/em&gt; are responsible for &lt;em&gt;which tasks&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Frame_42_(1).png&quot; alt=&quot;img/blog/client-side-architecture/Frame_42_(1).png&quot;&gt;&lt;/p&gt;
&lt;p&gt;In MVC and MVP, the model is ambiguous. This makes matching the correct tool up to the task feel like a puzzle.&lt;/p&gt;
&lt;h3 id=&quot;Tasks-of-the-model&quot; style=&quot;position:relative;&quot;&gt;Tasks of the model&lt;a href=&quot;#Tasks-of-the-model&quot; aria-label=&quot;Tasks of the model permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the real world, the model portion in most client-side web apps does a lot.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;State management —&lt;/strong&gt; Most apps need a way to fetch state, update state, and configure reactivity to when state changes, the &lt;em&gt;view&lt;/em&gt; can re-render.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Networking &amp;#x26; data fetching —&lt;/strong&gt; The actual &lt;em&gt;data-fetching&lt;/em&gt; concern is sometimes conflated as part of the model. The data fetching and networking aspect of an app need to know about backend services, formulate requests, handle responses, and marshal data, but it also needs to signal request &lt;em&gt;metadata&lt;/em&gt; (ie: &lt;code class=&quot;language-text&quot;&gt;isLoading&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;error&lt;/code&gt;). What about features like optimistic updates? Is that a concern of the model? I think it is.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Model behavior (ie: domain, app, or interaction logic) —&lt;/strong&gt; Deciding what happens next when a user clicks &lt;em&gt;submit&lt;/em&gt;, or wants to interact with something on the page is a form of &lt;em&gt;&lt;a href=&quot;/articles/client-side-architecture/layers#Interaction-layer&quot;&gt;interaction logic&lt;/a&gt;&lt;/em&gt;. Sometimes there are rules we need to enforce. They can be simple — like validation before sending off an API call. They can be complicated — like deciding if a chess piece can be dropped on the selected square.
Some call this &lt;em&gt;app logic&lt;/em&gt;, which I believe to be sufficient since it describes how our app responds to user events. Alternatively, I call it &lt;em&gt;interaction logic&lt;/em&gt; because it explains what happens in response to &lt;em&gt;user interaction&lt;/em&gt;.
There&apos;s one other kind of logic here, and that&apos;s &lt;em&gt;domain logic&lt;/em&gt;. Domain logic doesn&apos;t normally have anything to do with the application itself. Instead, it originates from an understanding of the domain. For example, while displaying a modal &lt;em&gt;before move a chess piece&lt;/em&gt; might be &lt;strong&gt;application/interaction logic&lt;/strong&gt;, enforcing the policy that &lt;em&gt;a knight can only move in an L-shaped fashion&lt;/em&gt; is a form of &lt;strong&gt;domain logic&lt;/strong&gt;. That rule originates from understanding the domain of &lt;em&gt;chess&lt;/em&gt; where the application-specific logic holds rules about how the user interacts with the app. Usually, domain logic lives behind backend services, and if we break the rules, we can get an error back as a response. Still, sometimes we co-locate it on the client-side, especially for more complex applications.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Authentication &amp;#x26; authorization logic (specific type of model behavior) —&lt;/strong&gt; This is another specific type of model behavior, but it&apos;s common enough to mention. Most of the time, authN &amp;#x26; authR finds itself being used from within the view layer (show &lt;em&gt;Login screen if not authenticated&lt;/em&gt;). Sometimes, it manifests in the &lt;strong&gt;application/interaction&lt;/strong&gt; layer as well, preventing access to specific operations.&lt;/p&gt;
&lt;h3 id=&quot;Tools-used-within-the-model&quot; style=&quot;position:relative;&quot;&gt;Tools used within the model&lt;a href=&quot;#Tools-used-within-the-model&quot; aria-label=&quot;Tools used within the model permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;These are all common challenges to solve. In 2020, the developer toolbox for a React developer looks a little something like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;React hooks&lt;/li&gt;
&lt;li&gt;Redux&lt;/li&gt;
&lt;li&gt;Context API&lt;/li&gt;
&lt;li&gt;Apollo Client&lt;/li&gt;
&lt;li&gt;xState&lt;/li&gt;
&lt;li&gt;react-query&lt;/li&gt;
&lt;li&gt;and now, recoil&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each of these are capable of addressing a particular piece of the &lt;em&gt;ambiguous model&lt;/em&gt; we described, but matching the correct tool to the proper concern can be tricky.&lt;/p&gt;
&lt;p&gt;Of course, it&apos;s tricky. We don&apos;t have a standard language to describe the different concerns. Instead of thinking about the tools right away, I think we need to back up and look at the bigger picture of the problems to be solved.&lt;/p&gt;
&lt;h2 id=&quot;We-need-a-shared-language-to-talk-about-client-side-architecture&quot; style=&quot;position:relative;&quot;&gt;We need a shared language to talk about client-side architecture&lt;a href=&quot;#We-need-a-shared-language-to-talk-about-client-side-architecture&quot; aria-label=&quot;We need a shared language to talk about client side architecture permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We need a shared language to describe these architectural concepts upon which we either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Configure a library or a framework to solve&lt;/li&gt;
&lt;li&gt;Write the code ourselves for&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most React developers know the implementation-specific terminology like hooks, reducers, context, and props, but architectural concerns are sometimes misunderstood.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Frame_37_(1).png&quot; alt=&quot;img/blog/client-side-architecture/Frame_37_(1).png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Having a shared understanding of what constitutes &lt;strong&gt;client-side architecture concerns&lt;/strong&gt; enables us to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have better design conversations&lt;/li&gt;
&lt;li&gt;Communicate which concerns are addressed by which tool&lt;/li&gt;
&lt;li&gt;Avoid code from concerns creeping too profoundly into another&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If we can, as a community, communicate a shared understanding of the concerns that make up the model (and the other parts), I think we can more easily answer questions like this: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Where do we put &lt;em&gt;application logic&lt;/em&gt; in a React/Redux app? What about an Apollo Client one? What about a [insert new library/framework here] one?&lt;/li&gt;
&lt;li&gt;Should I use container components?&lt;/li&gt;
&lt;li&gt;Should I put my GraphQL mutations inside of my component?&lt;/li&gt;
&lt;li&gt;Do I need to write tests for Apollo Client? Redux?&lt;/li&gt;
&lt;li&gt;What kind of logic should I put in a React hook?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&apos;ve got good news for you...&lt;/p&gt;
&lt;h2 id=&quot;Weve-already-solved-this-problem&quot; style=&quot;position:relative;&quot;&gt;We&apos;ve already solved this problem&lt;a href=&quot;#Weve-already-solved-this-problem&quot; aria-label=&quot;Weve already solved this problem permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&apos;s not discredit the software design and architecture research done over the last 30 years.&lt;/p&gt;
&lt;p&gt;While the tools and approaches to web development have changed at a miraculous pace, &lt;strong&gt;software design&lt;/strong&gt; &lt;strong&gt;principles and patterns have remarkably, remained the same&lt;/strong&gt;.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Knowledge drain&lt;/b&gt;: When (domain, trade, scientific) knowledge is lost or forgotten over time.&lt;/p&gt;
&lt;p&gt;Let&apos;s look at backend development. &lt;/p&gt;
&lt;p&gt;How did we solve the &lt;em&gt;ambiguous model&lt;/em&gt; problem when building out backend services?&lt;/p&gt;
&lt;p&gt;Initially, with MVC on the server, we thought the model could be &lt;em&gt;services&lt;/em&gt;, &lt;a href=&quot;https://sequelize.org/&quot;&gt;ORM&lt;/a&gt;s, or even the &lt;em&gt;database&lt;/em&gt; itself&lt;em&gt;.&lt;/em&gt; Each of these are &lt;em&gt;part&lt;/em&gt; of the model, but they&apos;re not the entire model.&lt;/p&gt;
&lt;p&gt;According to &lt;a href=&quot;https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller&quot;&gt;wikipedia&lt;/a&gt;, the &lt;strong&gt;model&lt;/strong&gt; is supposed to represent the &lt;strong&gt;data, logic, and any rules of the application&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;When backend developers discovered that &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;MVC doesn&apos;t provide enough insight as to how to structure the &lt;em&gt;model&lt;/em&gt; portion&lt;/a&gt;, we used design principles to create more advanced architectures, like the &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;clean architecture&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Frame_34_(1).png&quot; alt=&quot;img/blog/client-side-architecture/Frame_34_(1).png&quot;&gt;&lt;/p&gt;
&lt;p&gt;The clean architecture sheds more light on how to structure your backend in a testable and flexible way. It also helps accommodate for more advanced applications containing business logic.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;clean architecture&lt;/em&gt; (which has many similar variants — see layered, &lt;a href=&quot;https://khalilstemmler.com/articles/graphql/graphql-architectural-advantages/&quot;&gt;hexagonal architecture&lt;/a&gt;, or ports &amp;#x26; adapters) provides specifics as to what the &lt;code class=&quot;language-text&quot;&gt;M&lt;/code&gt; in the model is. &lt;/p&gt;
&lt;p&gt;By splitting the model into &lt;strong&gt;infrastructure,&lt;/strong&gt; &lt;strong&gt;application,&lt;/strong&gt; and &lt;strong&gt;domain&lt;/strong&gt; layers, we exercise the &lt;strong&gt;separation of concerns&lt;/strong&gt; design principle, and we&apos;re left with a much easier to reason about architecture. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Frame_43.png&quot; alt=&quot;img/blog/client-side-architecture/Frame_43.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;The middle layers (domain and application) are the purest. It&apos;s the code that &lt;em&gt;we,&lt;/em&gt; the developers, &lt;strong&gt;have to write from scratch&lt;/strong&gt;. And since our app doesn&apos;t do much unless we can hook it up to the real-world using things like web servers, databases, APIs, and caches, the &lt;em&gt;adapter layer&lt;/em&gt; provides a flexible way to integrate those &lt;strong&gt;infrastructural dependencies into our app, while keeping them distanced&lt;/strong&gt; from our domain and app layer code. &lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;To learn more about the clean architecture read &lt;a href=&quot;/articles/software-design-architecture/organizing-app-logic/&quot;&gt;Organizing App Logic with the Clean Architecture [with Examples]&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;A layered architecture like this comes at the cost of being more &lt;em&gt;complex&lt;/em&gt; than a simple single-tiered one, but let&apos;s be honest — &lt;strong&gt;sometimes we have to solve some &lt;em&gt;damn&lt;/em&gt; hard problems&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;layered&lt;/em&gt; architecture has a lot of benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It makes it &lt;strong&gt;extremely clear&lt;/strong&gt; which tools are needed at which layer of the stack.&lt;/li&gt;
&lt;li&gt;It keeps concerns separate and enables you to &lt;strong&gt;keep your app and domain layer code unit testable.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;It allows you to mock out expensive to test things, &lt;strong&gt;and swap libraries and frameworks&lt;/strong&gt; (not that you do that too often — but, in case you ever needed to, you can).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&apos;s hella cool.&lt;/p&gt;
&lt;p&gt;Quick question.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Where&apos;s our &lt;em&gt;client-side&lt;/em&gt; version of this?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;Client-side-needs--testability-flexibility-and-maintainability&quot; style=&quot;position:relative;&quot;&gt;Client-side needs — testability, flexibility, and maintainability&lt;a href=&quot;#Client-side-needs--testability-flexibility-and-maintainability&quot; aria-label=&quot;Client side needs  testability flexibility and maintainability permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&apos;s back up a bit. &lt;/p&gt;
&lt;p&gt;Before we discuss an equivalent client-side architecture, let&apos;s talk about our needs first.&lt;/p&gt;
&lt;p&gt;We don&apos;t want to dogmatically copy the clean architecture.&lt;/p&gt;
&lt;p&gt;What are we &lt;em&gt;really&lt;/em&gt; looking for when we talk about &lt;em&gt;architecture&lt;/em&gt; on the client-side? Why does any of this matter? Why don&apos;t we just write all of our code in a single file (actually, some of us &lt;em&gt;do&lt;/em&gt; write single file components)? Is architecture about &lt;em&gt;file organization&lt;/em&gt;, or is it about something more?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;It&apos;s about writing testable, flexible, and maintainable code&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;Testability&quot; style=&quot;position:relative;&quot;&gt;Testability&lt;a href=&quot;#Testability&quot; aria-label=&quot;Testability permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&apos;ve noticed that an alarming amount of developers don&apos;t write tests for their front-end code. &lt;/p&gt;
&lt;p&gt;It could be a conscious decision of &lt;em&gt;choosing&lt;/em&gt; not to write tests — which is one thing, but it could also be a lack of education for how to write code so that it can &lt;strong&gt;be tested&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I&apos;ve found that depending on your testing strategy, your needs to separate concerns changes. &lt;strong&gt;If you&apos;re only going to be writing integration tests, then separation of concerns matters less&lt;/strong&gt;. &lt;strong&gt;If you&apos;re going to be writing a lot of unit tests, then mocking is going to be your saving grace, and separation of concerns is paramount&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If you understand the app you&apos;re building and the complexity of it, you can kind-of gauge this upfront.&lt;/p&gt;
&lt;h3 id=&quot;div-classexpandable-sectionWhen-to-write-unit-testsdiv-classexpandable-section-button-onclicktoggleExpandableSectionunit-testsdivdiv&quot; style=&quot;position:relative;&quot;&gt;&lt;div class=&quot;expandable-section&quot;&gt;When to write unit tests&lt;div class=&quot;expandable-section-button&quot; onclick=&quot;toggleExpandableSection(&apos;unit-tests&apos;)&quot;&gt;+&lt;/div&gt;&lt;/div&gt;&lt;a href=&quot;#div-classexpandable-sectionWhen-to-write-unit-testsdiv-classexpandable-section-button-onclicktoggleExpandableSectionunit-testsdivdiv&quot; aria-label=&quot;div classexpandable sectionWhen to write unit testsdiv classexpandable section button onclicktoggleExpandableSectionunit testsdivdiv permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div id=&quot;unit-tests&quot; class=&quot;expandable-section-content&quot;&gt;
  &lt;p&gt;Unit testing is the preferred approach for testing your client app if there&apos;s a &lt;b&gt;heavy amount of interaction/app logic&lt;/b&gt;, like a metadata layer in a 3D rendered game, chess game logic, a boating application, or a streaming site like Twitch.&lt;/p&gt; 
  &lt;p&gt;If the accuracy of the most important use cases cannot be verified by merely observing the side effects in the view, then unit tests are the way to go.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;div-classexpandable-sectionWhen-to-write-integration-testsdiv-classexpandable-section-button-onclicktoggleExpandableSectionintegration-testsdivdiv&quot; style=&quot;position:relative;&quot;&gt;&lt;div class=&quot;expandable-section&quot;&gt;When to write integration tests&lt;div class=&quot;expandable-section-button&quot; onclick=&quot;toggleExpandableSection(&apos;integration-tests&apos;)&quot;&gt;+&lt;/div&gt;&lt;/div&gt;&lt;a href=&quot;#div-classexpandable-sectionWhen-to-write-integration-testsdiv-classexpandable-section-button-onclicktoggleExpandableSectionintegration-testsdivdiv&quot; aria-label=&quot;div classexpandable sectionWhen to write integration testsdiv classexpandable section button onclicktoggleExpandableSectionintegration testsdivdiv permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div id=&quot;integration-tests&quot; class=&quot;expandable-section-content&quot;&gt;
  &lt;p&gt;Kent C. Dodds recommends integration tests when 90% of your users&apos; primary use cases can be tested against by observing changes to the view in response to user interaction. In this case, we&apos;re talking about basic CRUD apps.
  &lt;/p&gt;
  &lt;p&gt;The view is an implementation detail, and it&apos;s recommended to not test against implementation details. &lt;a href=&quot;https://testing-library.com/&quot;&gt;Testing library&lt;/a&gt; provides an excellent suite of tools to run integration tests on React apps through the view without focusing on implementation details.&lt;/p&gt;
&lt;/div&gt;
    
&lt;h3 id=&quot;Flexibility&quot; style=&quot;position:relative;&quot;&gt;Flexibility&lt;a href=&quot;#Flexibility&quot; aria-label=&quot;Flexibility permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It&apos;s not so often that we need to switch from REST to GraphQL or swap out APIs, but there are a select few cases that we should enable flexibility for.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Swapping out view components —&lt;/strong&gt; Keeping app logic out of your presentational components allows you to swap out how the component looks from how it works, as painlessly as humanly possible.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Changing model behavior —&lt;/strong&gt; If your app is the interaction-logic heavy kind of app that needs lots of unit tests, using &lt;a href=&quot;https://khalilstemmler.com/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;dependency inversion&lt;/a&gt; to mock out API and framework code enables you to run fast tests against the behavior of the model.&lt;/p&gt;
&lt;h3 id=&quot;Maintainability&quot; style=&quot;position:relative;&quot;&gt;Maintainability&lt;a href=&quot;#Maintainability&quot; aria-label=&quot;Maintainability permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Maintainability is our ability to constantly provide value. If we struggle to change code or add new features, maintainability is low. &lt;/p&gt;
&lt;p&gt;It&apos;s worthy to note that if developer experience is low, there&apos;s a &lt;em&gt;chance&lt;/em&gt; maintainability is low as well.&lt;/p&gt;
&lt;p&gt;Here&apos;s an argument to challenge everything I&apos;ve praised about a &lt;em&gt;clean architecture&lt;/em&gt; so far. Looking at it from another point of view, &lt;em&gt;too many layers&lt;/em&gt; and &lt;em&gt;too many rules&lt;/em&gt; traditionally yields low developer experience for newer developers less familiar with the approach. &lt;/p&gt;
&lt;p&gt;This might be why so many new developers prefer to use React over Angular. Angular is actually quite opinionated and forces you towards a particular style of architecture. React lets you do whatever.&lt;/p&gt;
&lt;p&gt;There&apos;s a balance to be struck here. We want the structure of architecture, but we want the developer experience of knowing what to do and having the freedom to do it however we want. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Design&lt;/strong&gt; is the balance of conflicting priorities&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Office furniture = cost vs. quality&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Note-taking = context vs. compression &lt;br/&gt; — Tiago Forte&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And more relevant to us:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Software design = structure vs. developer experience&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I believe that developers who care not only about getting the job done but also getting it done &lt;em&gt;right&lt;/em&gt; will push through learning curves.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Client-Side Architecture Basics [Guide]]]></title><description><![CDATA[Welcome When I first learned React and Redux in 2015, I made an enormous mess of the production codebase I was working on. Back then, class…]]></description><link>https://khalilstemmler.com/articles/client-side-architecture/introduction/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/client-side-architecture/introduction/</guid><pubDate>Wed, 24 Jun 2020 15:04:10 GMT</pubDate><content:encoded>&lt;h2 id=&quot;Welcome&quot; style=&quot;position:relative;&quot;&gt;Welcome&lt;a href=&quot;#Welcome&quot; aria-label=&quot;Welcome permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When I first learned React and Redux in 2015, I made an enormous mess of the production codebase I was working on.&lt;/p&gt;
&lt;p&gt;Back then, class-based components and Redux were the coolest kids on the block. This was my first time prepping up to work on a real-world React project, so I bought the best courses I could find on the topics and dove in.&lt;/p&gt;
&lt;p&gt;After a couple of months, according to the React community, the way I was doing things were outdated. There were newer, cleaner, and recommended &lt;em&gt;best practices&lt;/em&gt; for me to follow.&lt;/p&gt;
&lt;p&gt;I think it&apos;s incredible that we question the way we do things. But my vast gap in knowledge of client-side architecture left me always finding it necessary to play catch up to refactor to the &lt;em&gt;new&lt;/em&gt; approaches.  &lt;/p&gt;
&lt;p&gt;These sentiments were also recently echoed in this painfully accurate Twitter thread from &lt;a href=&quot;https://twitter.com/jhooks&quot;&gt;Joel Hooks&lt;/a&gt;. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Developers are confused about where to start and what to choose when they start learning to write high-quality React applications. They want a strong foundation of knowledge and the confidence to architect React applications at scale built to current industry standards. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;They are frustrated that there are no widely accepted standards for building React applications consistently, coherently, and &lt;strong&gt;with minimal risks to their professional reputations and livelihoods&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;On top of that, there is a sea of choices and tradeoffs that React developers face every day. From how the project is even started, which framework to use, how to manage state, how does it get bundled, accessibility, and deployment just to get going.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;At each f🐬kin&apos; stop, there&apos;s a new choice to make: a new chance to be wrong.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Trying to build a solid foundation in React feels like a slot machine. — &lt;a href=&quot;https://twitter.com/jhooks/status/1273392253646434304&quot;&gt;@jhooks, June 17th, 2020&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Some point later in my developer journey, I too realized this was happening. I realized I could never keep up to date with the current trends of the libraries and frameworks I was using. I also decided I didn&apos;t want those nuances to dictate my professional reputation or livelihood. It wasn&apos;t good enough for me. I needed something better.&lt;/p&gt;
&lt;p&gt;Eventually, I sought out the originating principles— the fundamentals, to client-side architecture. I sought out to construct a standard for building client-side apps. A professional one. One based on the software design principles that have helped us design robust software for decades.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This guide teaches you client-side architecture fundamentals. &lt;/p&gt;
&lt;p&gt;It&apos;s the result of my research using &lt;a href=&quot;https://www.julian.com/blog/mental-model-examples&quot;&gt;first principles&lt;/a&gt; on how to &lt;strong&gt;design and develop robust, flexible, testable, and maintainable client-side applications.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;During my experience working on client-side apps of varying sizes, I&apos;ve realized that  &lt;strong&gt;&lt;em&gt;some&lt;/em&gt; serious upfront design&lt;/strong&gt; on the architecture can have a significant impact on the quality of the code for the duration of its life.&lt;/p&gt;
&lt;p&gt;From simple dashboards to multi-layered apps with rendering layers, domain logic, multiple types of users - this guide teaches you the essential design principles front-end developers inadvertently code around within their everyday programming jobs. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This guide proposes architectural standards for client-side web development&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;While we&apos;re primarily focused on React, because it&apos;s the most popular library with the least structure, the principles are transferrable to any configuration of view-layer library or framework. &lt;/p&gt;
&lt;p&gt;Programming tends to seem more like a trade than a science. Each tool, be it a state management library, API, or a transport-layer technology, is best suited to solve a particular set of problems. As a developer and a tradesperson, it&apos;s good to know how the tools in our toolbox are best used. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;... if all you have is a hammer, everything looks like a nail.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;At the end of this guide, you&apos;ll learn a standard for web development. You&apos;ll have a clear understanding of the &lt;strong&gt;&lt;a href=&quot;/articles/client-side-architecture/layers&quot;&gt;discrete layers of concerns&lt;/a&gt;&lt;/strong&gt; in a client-side app: from the view layer to various forms of state management, and how to handle interaction (app) logic. &lt;/p&gt;
&lt;h2 id=&quot;Prerequisites&quot; style=&quot;position:relative;&quot;&gt;Prerequisites&lt;a href=&quot;#Prerequisites&quot; aria-label=&quot;Prerequisites permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Familiarity with at least one front-end &lt;em&gt;view layer&lt;/em&gt; library (like React) or an opinionated framework like Angular. &lt;/li&gt;
&lt;li&gt;Knowledge of at least one state management approach (like React Context, Redux, Angular services, NgRx, etc).&lt;/li&gt;
&lt;li&gt;(optional) &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;Knowing When CRUD &amp;#x26; MVC Isn&apos;t Enough | Enterprise Node.js + TypeScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;(optional) &lt;a href=&quot;https://www.youtube.com/watch?v=tBz3UmZG_bk&quot;&gt;&quot;A Treatise on State&quot; by Jed Watson&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[II. Principles]]></title><description><![CDATA[This is page two of a guide on Client-Side Architecture basics. Start at page one. The most influential client-side architecture design…]]></description><link>https://khalilstemmler.com/articles/client-side-architecture/principles/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/client-side-architecture/principles/</guid><pubDate>Wed, 24 Jun 2020 15:04:10 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;This is page two of a guide on Client-Side Architecture basics. Start at &lt;a href=&quot;/articles/client-side-architecture/introduction&quot;&gt;page one&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;The-most-influential-client-side-architecture-design-principles&quot; style=&quot;position:relative;&quot;&gt;The most influential client-side architecture design principles&lt;a href=&quot;#The-most-influential-client-side-architecture-design-principles&quot; aria-label=&quot;The most influential client side architecture design principles permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While the &lt;em&gt;clean architecture&lt;/em&gt; works, we don&apos;t need a copy of it on the client-side. However, I &lt;em&gt;do&lt;/em&gt; think it&apos;s a good idea to look at the same design principles and practices that formed it and apply those to the client.&lt;/p&gt;
&lt;p&gt;You&apos;ll notice that each principle, in some way, is about enforcing some structural constraints as to what can be done, and how things are organized. &lt;/p&gt;
&lt;p&gt;In my opinion, these are the &lt;strong&gt;most crucial&lt;/strong&gt; design principles. They influence 90% of what constitutes good client-side architecture. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Command-Query Separation&lt;/li&gt;
&lt;li&gt;Separation of Concerns&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Command-Query-Separation&quot; style=&quot;position:relative;&quot;&gt;Command Query Separation&lt;a href=&quot;#Command-Query-Separation&quot; aria-label=&quot;Command Query Separation permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Separate methods that change state from those that don&apos;t&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Command Query Separation is a design principle that states that an operation is either a &lt;code class=&quot;language-text&quot;&gt;command&lt;/code&gt; or a &lt;code class=&quot;language-text&quot;&gt;query&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;commands&lt;/code&gt; change state but return no data, and&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;queries&lt;/code&gt; return data but don&apos;t change state.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Frame_44_(2).png&quot; alt=&quot;img/blog/client-side-architecture/Frame_44_(2).png&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Operations&lt;/strong&gt; are the same thing as &lt;em&gt;interactions&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The primary benefit of this pattern is that it makes code &lt;strong&gt;easier to reason about&lt;/strong&gt;. Ultimately, it urges us to carve out two code paths: one for &lt;em&gt;reads&lt;/em&gt;, and one for &lt;em&gt;writes&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;The simplest way to see it in action is at the &lt;em&gt;method-level.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;Commands&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Commands&lt;/strong&gt;&lt;a href=&quot;#Commands&quot; aria-label=&quot;Commands permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Consider the methods &lt;code class=&quot;language-text&quot;&gt;createUser&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;selectTodo&lt;/code&gt;. These are both &lt;code class=&quot;language-text&quot;&gt;command&lt;/code&gt;-like operations. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserDetails&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
function selectTodo (todoId: number): void &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice that neither of these methods return anything. They&apos;re both &lt;code class=&quot;language-text&quot;&gt;void&lt;/code&gt;. That&apos;s what a valid &lt;code class=&quot;language-text&quot;&gt;command&lt;/code&gt; is. &lt;/p&gt;
&lt;p&gt;That means that the following methods aren&apos;t valid commands.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
function selectTodo (): Todo &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Queries&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Queries&lt;/strong&gt;&lt;a href=&quot;#Queries&quot; aria-label=&quot;Queries permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Queries are operations that return data and perform no side-effects. Like these, for example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getCurrentUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
function getUserById (userId: UserId): Promise&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Why-does-it-matter&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Why does it matter?&lt;/strong&gt;&lt;a href=&quot;#Why-does-it-matter&quot; aria-label=&quot;Why does it matter permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Simplifies the code paths — this is what React hooks does with the accessor/mutator API of &lt;code class=&quot;language-text&quot;&gt;useState&lt;/code&gt;, and what GraphQL does with &lt;code class=&quot;language-text&quot;&gt;queries&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;mutations&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Operations are easier to reason about — consider how hard (and disastrous) it would be to test a &lt;code class=&quot;language-text&quot;&gt;query&lt;/code&gt; was working properly if it always also performed a side-effect that changed the state of the system.&lt;/li&gt;
&lt;li&gt;All &lt;em&gt;features&lt;/em&gt; can be thought about as operations: &lt;code class=&quot;language-text&quot;&gt;commands&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;queries&lt;/code&gt;. If you want to make sure that all your features have integration tests, ensure a good separation of &lt;code class=&quot;language-text&quot;&gt;commands&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;queries&lt;/code&gt; that the user performs, and test each one.
One other interesting discovery: since most &lt;strong&gt;pages/routes&lt;/strong&gt; in your app invoke one or more &lt;em&gt;features,&lt;/em&gt; a potentially maintainable folder structure could be formed by &lt;a href=&quot;https://kentcdodds.com/blog/colocation&quot;&gt;co-locating&lt;/a&gt; all the concerns and components by features, and then by page/route. The folks behind React Router seem to be on a similar &lt;em&gt;page&lt;/em&gt; (sorry); their new project, &lt;a href=&quot;https://remix.run/&quot;&gt;Remix&lt;/a&gt;, features file system routes and route layout nesting.&lt;/li&gt;
&lt;li&gt;Apparently, cache invalidation is one of the hardest problems in computer science. It&apos;s easier with this. Using CQS, we can be sure that when if no new &lt;code class=&quot;language-text&quot;&gt;commands&lt;/code&gt; were executed (against a particular item), we can continue to perform &lt;code class=&quot;language-text&quot;&gt;queries&lt;/code&gt; for directly from the cache. The moment a &lt;code class=&quot;language-text&quot;&gt;command&lt;/code&gt; is executed, we invalidate the item in the cache. Consider how this might be useful for a state management library.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Separation-of-Concerns&quot; style=&quot;position:relative;&quot;&gt;Separation of Concerns&lt;a href=&quot;#Separation-of-Concerns&quot; aria-label=&quot;Separation of Concerns permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Consciously enforcing logical boundaries between each of the architectural concerns of your app&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Assume we have a list of todos. &lt;/p&gt;
&lt;p&gt;When a user clicks &lt;em&gt;delete&lt;/em&gt; on the todo, what happens next?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Todo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;todo-text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onDeleteTodo&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Delete&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Well, the &lt;em&gt;view&lt;/em&gt; passes off the event to a container. That could connect the user event to a method from a React Hook or a Redux thunk. From there, we might want to run some logic, decide if we should invoke a network request, update the state stored locally, then somehow notify the UI that it should update.&lt;/p&gt;
&lt;p&gt;That&apos;s a lot. And that&apos;s a &lt;em&gt;simple&lt;/em&gt; app. And when I said we might want to &lt;em&gt;run some logic&lt;/em&gt; a moment ago, I wasn&apos;t clear about &lt;strong&gt;exactly&lt;/strong&gt; what kinds of logic it could be. It could be authorization logic, validation logic, interaction/domain logic, etc. Instead of putting five different kinds of logic &lt;em&gt;wherever&lt;/em&gt;, we can classify it, carve out a place for it to live, and be more structured and conscious about how we connect features together.&lt;/p&gt;
&lt;p&gt;Separation of concerns is one of my favorite design principles. It&apos;s about thinking the jobs to be done, delegating them to a particular layer that handles those concerns, and then ensuring those layers do their jobs, and their jobs &lt;em&gt;only&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Frame_46_(1).png&quot; alt=&quot;img/blog/client-side-architecture/Frame_46_(1).png&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;How-separation-of-concerns-and-CQS-work-together&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;How separation of concerns and CQS work together&lt;/strong&gt;&lt;a href=&quot;#How-separation-of-concerns-and-CQS-work-together&quot; aria-label=&quot;How separation of concerns and CQS work together permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;CQS said that every &lt;em&gt;feature&lt;/em&gt; is an operation. It also said that every operation is either a &lt;code class=&quot;language-text&quot;&gt;command&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;query&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;This means that every &lt;em&gt;feature&lt;/em&gt; cuts through several concerns to work. &lt;/p&gt;
&lt;p&gt;I like to think of features as &lt;strong&gt;&lt;em&gt;vertical slices&lt;/em&gt; that cut through the stack.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;Features-are-vertical-slices&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Features are vertical slices&lt;/strong&gt;&lt;a href=&quot;#Features-are-vertical-slices&quot; aria-label=&quot;Features are vertical slices permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When we add or change features in an application, we&apos;re modifying a part of the vertical slice for that feature. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Frame_49.png&quot; alt=&quot;img/blog/client-side-architecture/Frame_49.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Need to change the way the login component looks? No problem, you&apos;re going to add some styles to the presentational component in the presentation layer &lt;em&gt;from the Login feature&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Need to change what happens a when todo open for longer than 30 days was just completed? Want to throw confetti on the screen and say how proud of the user you are? Gotcha. Add some logic to the &lt;a href=&quot;https://xstate.js.org/docs/recipes/react.html#hooks&quot;&gt;xState model&lt;/a&gt; from the interaction layer for the &lt;em&gt;Complete Todo&lt;/em&gt; feature.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Frame_50.png&quot; alt=&quot;img/blog/client-side-architecture/Frame_50.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;I&apos;m a huge fan of this.&lt;/p&gt;
&lt;p&gt;Understanding the responsibilities of each layer enables us to better reason about which tools to use &lt;strong&gt;per feature&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;Using Apollo Client, React Hooks + xState&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Application logic: Hooks + xState&lt;/li&gt;
&lt;li&gt;State management: Apollo Client (global state)&lt;/li&gt;
&lt;li&gt;Data fetching: Apollo Client&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using Apollo Client and plain JavaScript&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Interaction logic: Hooks + &lt;a href=&quot;https://github.com/xolvio/pojo-observer&quot;&gt;pojo-observer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;State Management: Apollo Client (global state)&lt;/li&gt;
&lt;li&gt;Data fetching: Apollo Client&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using REST, Redux, and React Hooks&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Interaction logic: Hooks&lt;/li&gt;
&lt;li&gt;State Management: Redux (global state). Connect for observability/reactivity, and Thunks for signaling async states.&lt;/li&gt;
&lt;li&gt;Data fetching: Fetch or Axios&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I first heard of the term &lt;em&gt;vertical slices&lt;/em&gt; from &lt;a href=&quot;https://jimmybogard.com/vertical-slice-architecture/&quot;&gt;Jimmy Bogard&lt;/a&gt;. Thinking of features this way reduces the amount of time it takes for developers to figure out where to add or change code.&lt;/p&gt;
&lt;p&gt;This is where developers get stuck, figuring out what the layers of the stack are, and which tools can be used at each layer of the stack.&lt;/p&gt;
&lt;p&gt;Vertical slices enables us to keep &lt;a href=&quot;https://khalilstemmler.com/articles/solid-principles/single-responsibility/&quot;&gt;Single Responsibility&lt;/a&gt; high if we &quot;minimize coupling between slices, and maximize coupling in a slice&quot; — via &lt;a href=&quot;https://jimmybogard.com/vertical-slice-architecture/&quot;&gt;Jimmy Bogard&lt;/a&gt;. Also read Kent C. Dodd&apos;s article on &quot;&lt;a href=&quot;https://kentcdodds.com/blog/colocation&quot;&gt;Co-location&lt;/a&gt;&quot;.&lt;/p&gt;
&lt;h3 id=&quot;Why-does-it-matter-1&quot; style=&quot;position:relative;&quot;&gt;&lt;strong&gt;Why does it matter?&lt;/strong&gt;&lt;a href=&quot;#Why-does-it-matter-1&quot; aria-label=&quot;Why does it matter 1 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Better visibility as to which tasks need to be done, which layer they belong to, and which tools can be used to address those concerns.&lt;/li&gt;
&lt;li&gt;Helps to decide whether we want to implement a layer ourselves or use a framework/library. For example, most developers won&apos;t build their own view-layer library for presentational components — they&apos;ll use React or Vue. But lots of users &lt;strong&gt;&lt;em&gt;will&lt;/em&gt; build their own state management system from scratch&lt;/strong&gt; using Redux and Connect.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[III. Layers]]></title><description><![CDATA[This is page three of a guide on Client-Side Architecture basics. Start at page one. Layers and concerns We're finally ready to decompose…]]></description><link>https://khalilstemmler.com/articles/client-side-architecture/layers/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/client-side-architecture/layers/</guid><pubDate>Wed, 24 Jun 2020 15:04:10 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;This is page three of a guide on Client-Side Architecture basics. Start at &lt;a href=&quot;/articles/client-side-architecture/introduction&quot;&gt;page one&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;Layers-and-concerns&quot; style=&quot;position:relative;&quot;&gt;Layers and concerns&lt;a href=&quot;#Layers-and-concerns&quot; aria-label=&quot;Layers and concerns permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&apos;re finally ready to decompose each part of Model-View-Presenter, especially the &lt;em&gt;model&lt;/em&gt; part.&lt;/p&gt;
&lt;p&gt;Here&apos;s a graphic to illustrate that decomposition into something more concrete.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Client-side_architecture_basics_(5).png&quot; alt=&quot;img/blog/client-side-architecture/Client-side_architecture_basics_(5).png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Can you see both CQS and SoC in here?&lt;/p&gt;
&lt;p&gt;Let&apos;s examine it from the top.&lt;/p&gt;
&lt;h2 id=&quot;Presentation-components&quot; style=&quot;position:relative;&quot;&gt;Presentation components&lt;a href=&quot;#Presentation-components&quot; aria-label=&quot;Presentation components permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Render the UI and create user events&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you read the title and feel like closing the tab because of &lt;em&gt;&lt;a href=&quot;https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0&quot;&gt;this article&lt;/a&gt;&lt;/em&gt; by Dan Abramov, hang in there. Just wait until we get to container components to decide if you want to bounce 🏀.&lt;/p&gt;
&lt;p&gt;Presentation components live within the boundaries of the &lt;em&gt;View&lt;/em&gt; portion of Model-View-Presenter. Their entire purpose is to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Display data in the UI&lt;/li&gt;
&lt;li&gt;Generate user events (from keypresses, button clicks, hover states, etc)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Presentation-components-are-an-implementation-detail&quot; style=&quot;position:relative;&quot;&gt;Presentation components are an implementation detail&lt;a href=&quot;#Presentation-components-are-an-implementation-detail&quot; aria-label=&quot;Presentation components are an implementation detail permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;An implementation detail is a low-level detail that helps us accomplish our &lt;em&gt;main&lt;/em&gt; goal. But they&apos;re not our &lt;em&gt;main&lt;/em&gt; goal. If our &lt;em&gt;main&lt;/em&gt; goal is to hook up the &lt;em&gt;Add Todo&lt;/em&gt; feature, the buttons, styling, and text in the UI is an implementation detail in realizing the feature.&lt;/p&gt;
&lt;h3 id=&quot;Presentation-components-can-be-volatile&quot; style=&quot;position:relative;&quot;&gt;Presentation components can be volatile&lt;a href=&quot;#Presentation-components-can-be-volatile&quot; aria-label=&quot;Presentation components can be volatile permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Anything subject to frequent change is said to be &lt;em&gt;volatile&lt;/em&gt;. Us constantly changing the look and feel of components is what makes them so. &lt;/p&gt;
&lt;p&gt;One way to accommodate this phenomenon is to decide on a &lt;strong&gt;&lt;a href=&quot;https://khalilstemmler.com/wiki/stable-dependency-principle/&quot;&gt;stable&lt;/a&gt;&lt;/strong&gt; set of reusable components (that either you wrote or grabbed from a component library), then create your views from those.&lt;/p&gt;
&lt;p&gt;Even though we could use reusable components, data requirements change frequently. &lt;/p&gt;
&lt;p&gt;Take this simple &lt;code class=&quot;language-text&quot;&gt;CardDescription&lt;/code&gt; component that uses a GraphQL query to describe a card.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CARD_DESCRIPTION_QUERY&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; gql&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
  query CardDescription($cardId: ID!) {
    card(id: $cardId) {
      description
    }
  }
&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;CardDescription&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; cardId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; loading &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    query&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CARD_DESCRIPTION_QUERY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    variables&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; cardId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;loading&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;card&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;description&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;How likely is it that we&apos;d need to change the styling? What about displaying something like a &lt;code class=&quot;language-text&quot;&gt;lastChanged&lt;/code&gt; date beside it? Chances are we pretty likely.&lt;/p&gt;
&lt;h3 id=&quot;Should-we-include-GraphQL-queries-in-our-presentation-components&quot; style=&quot;position:relative;&quot;&gt;Should we include GraphQL queries in our presentation components?&lt;a href=&quot;#Should-we-include-GraphQL-queries-in-our-presentation-components&quot; aria-label=&quot;Should we include GraphQL queries in our presentation components permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It&apos;s good to have GraphQL queries &lt;strong&gt;as close to the presentational component as possible&lt;/strong&gt;. Queries define the data requirements. And since they&apos;ll likely need to be changed together if the requirements change, having them close together reduces unnecessary cognitive load accrued by flipping back and forth between files.&lt;/p&gt;
&lt;p&gt;One potential &lt;em&gt;downside&lt;/em&gt; to putting your queries in your components is that now, if you ever wanted to switch away from GraphQL, your components aren&apos;t pure— they&apos;re coupled to GraphQL. If you wanted to switch transport-layer technologies, you&apos;d have to refactor every component.&lt;/p&gt;
&lt;p&gt;Another potential downside is that to test these components, you&apos;d need to make sure they&apos;re wrapped in a &lt;a href=&quot;https://www.apollographql.com/docs/react/development-testing/testing/#mockedprovider&quot;&gt;mocked Apollo Client provider&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My recommendation is to couple the queries to the components anyways. What you gain in an incredible developer experience is, in my opinion, worth the risk of going fully in with GraphQL and deciding you want to change later down the road.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note on query performance&lt;/strong&gt;: It&apos;s ok to have lots of queries for super-specific chunks of data like shown above. Using Apollo Client, Apollo handles that complicated logic of checking whether the data is cached already, and if not — it makes a request to get it.&lt;/p&gt;
&lt;h3 id=&quot;What-to-test-in-presentation-components&quot; style=&quot;position:relative;&quot;&gt;What to test in presentation components&lt;a href=&quot;#What-to-test-in-presentation-components&quot; aria-label=&quot;What to test in presentation components permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Unit testing implementation details is typically fruitless — especially for volatile things. It doesn&apos;t do us much good testing to see if a button is blue or green. Instead, when testing presentation components, we want to test against UI logic.&lt;/p&gt;
&lt;p&gt;To demonstrate what I mean, here&apos;s a bland, basic presentation component.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;/components/Todo.tsx&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Todo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;todo-text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onDeleteTodo&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Delete&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There&apos;s no UI logic involved here. It merely takes in props, hooks up callbacks, and renders some HTML.&lt;/p&gt;
&lt;p&gt;Here&apos;s &lt;em&gt;another&lt;/em&gt; example of the same component, but this time, as a class-based component with &lt;strong&gt;UI logic&lt;em&gt;.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;/components/Todo.tsx&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Component &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; PropTypes &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;prop-types&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; classnames &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;classnames&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; TodoTextInput &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./TodoTextInput&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Props &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Todo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Component&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Props&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; propTypes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    todo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PropTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isRequired&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    editTodo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PropTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;func&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isRequired&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    deleteTodo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PropTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;func&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isRequired&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    completeTodo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PropTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;func&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isRequired
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    editing&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function-variable function&quot;&gt;handleDoubleClick&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; editing&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function-variable function&quot;&gt;handleSave&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;deleteTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;editTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; editing&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; todo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; completeTodo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; deleteTodo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;editing &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;TodoTextInput&lt;/span&gt;&lt;/span&gt; 
          &lt;span class=&quot;token attr-name&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token attr-name&quot;&gt;editing&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;editing&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token attr-name&quot;&gt;onSave&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;text&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;handleSave&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;view&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; 
           &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;toggle&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
           &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
           &lt;span class=&quot;token attr-name&quot;&gt;checked&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;completed&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
           &lt;span class=&quot;token attr-name&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;completeTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onDoubleClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handleDoubleClick&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; 
          &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;destroy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token attr-name&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;deleteTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;UI-logic&quot; style=&quot;position:relative;&quot;&gt;UI logic&lt;a href=&quot;#UI-logic&quot; aria-label=&quot;UI logic permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;View behavior &amp;#x26; local component state&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The main difference between the two previously shown &lt;code class=&quot;language-text&quot;&gt;Todo&lt;/code&gt; components is that the second &lt;code class=&quot;language-text&quot;&gt;Todo&lt;/code&gt; component contained UI logic where the first did not.&lt;/p&gt;
&lt;h3 id=&quot;UI-logic-is-view-behavior&quot; style=&quot;position:relative;&quot;&gt;UI logic is view behavior&lt;a href=&quot;#UI-logic-is-view-behavior&quot; aria-label=&quot;UI logic is view behavior permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Frame_51_(3).png&quot; alt=&quot;img/blog/client-side-architecture/Frame_51_(3).png&quot;&gt;&lt;/p&gt;
&lt;p&gt;&quot;If you&apos;re logged in, show &lt;em&gt;this&lt;/em&gt; — otherwise, show &lt;em&gt;this.&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&quot;If you&apos;re this type of user, show &lt;em&gt;this&lt;/em&gt; — otherwise, show &lt;em&gt;this.&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&quot;Depending on which page you&apos;re on in the signup process, show the correct form&quot;.&lt;/p&gt;
&lt;p&gt;A component has UI logic when it exudes behavior. Conditionals that determine &lt;em&gt;what to show&lt;/em&gt;, or &lt;em&gt;when certain user events get called over others&lt;/em&gt; &lt;strong&gt;are a form of view behavior (UI logic)&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here&apos;s a conditional example from the previous code sample &lt;strong&gt;determining what to show&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;editing &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;TodoTextInput&lt;/span&gt;&lt;/span&gt; 
        &lt;span class=&quot;token attr-name&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;editing&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;editing&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;onSave&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;text&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;handleSave&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;view&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; 
         &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;toggle&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
         &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
         &lt;span class=&quot;token attr-name&quot;&gt;checked&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;completed&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
         &lt;span class=&quot;token attr-name&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;completeTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onDoubleClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handleDoubleClick&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; 
        &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;destroy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;deleteTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here&apos;s a conditional &lt;strong&gt;determining which user event to create&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token function-variable function&quot;&gt;handleSave&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;deleteTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;editTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; editing&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Component--local-state&quot; style=&quot;position:relative;&quot;&gt;Component / local state&lt;a href=&quot;#Component--local-state&quot; aria-label=&quot;Component  local state permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is where the &lt;em&gt;first&lt;/em&gt; type of state we might encounter: &lt;code class=&quot;language-text&quot;&gt;local (component)&lt;/code&gt; state.&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;https://twitter.com/JedWatson&quot;&gt;Jed Watson&lt;/a&gt;&apos;s talk from GraphQL Summit 2019 titled, &quot;&lt;a href=&quot;https://www.youtube.com/watch?v=tBz3UmZG_bk&amp;#x26;feature=emb_title&quot;&gt;A Treatise on State&lt;/a&gt;&quot;, he describes five different types of state when building web apps: &lt;code class=&quot;language-text&quot;&gt;local (component)&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;shared (global)&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;remote (global)&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;meta&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;router&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Explanations of the five types of state&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;local (component)&lt;/code&gt; : State that belongs to a single component. Can also be thought about as UI state. UI state can be extracted from a presentation component into a React hook. &lt;strong&gt;Note: we&apos;re about to do this&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;shared (global)&lt;/code&gt; : As soon as some state belongs to more than one component, it&apos;s &lt;em&gt;shared&lt;/em&gt; global state. Components shouldn&apos;t need to know about each other (a header shouldn&apos;t need to know about a todo).&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;remote (global)&lt;/code&gt; : The state that exists behind APIs in services. When we make &lt;code class=&quot;language-text&quot;&gt;queries&lt;/code&gt; for remote state, we hold onto a local copy of it accessible from a global scope.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;meta&lt;/code&gt; : Meta state refers to state &lt;em&gt;about&lt;/em&gt; state. The best example of this is the &lt;code class=&quot;language-text&quot;&gt;loading&lt;/code&gt; async states that tell us the progress of our network requests.&lt;/li&gt;
&lt;li&gt;and &lt;code class=&quot;language-text&quot;&gt;router&lt;/code&gt; state: The current URL of the browser.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This state, &lt;code class=&quot;language-text&quot;&gt;local (component)&lt;/code&gt; state, belongs to a single component. You can call this UI state. It&apos;s meant to hold onto data that helps a single component do its job. &lt;/p&gt;
&lt;p&gt;To better see what it looks like, let&apos;s extract all UI state from this class-based component and refactor to a functional component and a React hook. &lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;/components/Todo.tsx&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Component &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; PropTypes &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;prop-types&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; classnames &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;classnames&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; TodoTextInput &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./TodoTextInput&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; useState &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Decompose the UI logic from the presentational component
 * and store it in a React hook.
 *
 * All data and operations in this hook are UI logic for the
 * component - we&apos;ve just separated concerns, that&apos;s all.
 */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useTodoComponent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// &quot;editing&quot; is a form of local (component) state&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;editing&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setEditing&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handleSave&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      actions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;deleteTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      actions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;editTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setEditing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;handleDoubleClick&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setEditing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    models&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; editing &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    operations&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; handleSave&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handleDoubleClick &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * This component relies on some local state, but none of 
 * it lives within the component, which is purely 
 * presentational.
 */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Todo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; todo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; actions &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;// Grab our local (component) state and access to other UI logic&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; operations &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useTodoComponent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;actions&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;// Conditional UI logic&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;editing &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;TodoTextInput&lt;/span&gt;&lt;/span&gt; 
      &lt;span class=&quot;token attr-name&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token attr-name&quot;&gt;editing&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;editing&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token attr-name&quot;&gt;onSave&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;text&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; operations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;handleSave&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;view&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; 
        &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;toggle&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;checked&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;completed&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; actions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;completeTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;onDoubleClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;operations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handleDoubleClick&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; 
        &lt;span class=&quot;token attr-name&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;destroy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; actions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;deleteTodo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;UI-logic-is-what-we-actually-try-to-test-within-components&quot; style=&quot;position:relative;&quot;&gt;UI logic is what we &lt;em&gt;actually&lt;/em&gt; try to test within components&lt;a href=&quot;#UI-logic-is-what-we-actually-try-to-test-within-components&quot; aria-label=&quot;UI logic is what we actually try to test within components permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Since UI logic is behavior, &lt;em&gt;this&lt;/em&gt; is actually what we want to test against in our integration tests. The behavior. You &lt;em&gt;could&lt;/em&gt; write unit tests as well, but it might be trivial if component logic is straightforward. It could be more worthwhile and give you more confidence that the feature is working correctly to integration test both the component and the UI logic together.&lt;/p&gt;
&lt;h2 id=&quot;Containercontroller&quot; style=&quot;position:relative;&quot;&gt;Container/controller&lt;a href=&quot;#Containercontroller&quot; aria-label=&quot;Containercontroller permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;The glue layer (pages)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Traditionally, the responsibilities of a container component were to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Consume user events &amp;#x26; pass them to the model&lt;/li&gt;
&lt;li&gt;Subscribe to data changes (reactivity) and keep the view updated&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Frame_52_(1).png&quot; alt=&quot;img/blog/client-side-architecture/Frame_52_(1).png&quot;&gt;&lt;/p&gt;
&lt;p&gt;This isn&apos;t new. The definition of a &lt;em&gt;controller/presenter,&lt;/em&gt; all the way back from the &lt;em&gt;Model-View-Presenter&lt;/em&gt; pattern, made this distinction.&lt;/p&gt;
&lt;h3 id=&quot;Do-we-really-need-container-components&quot; style=&quot;position:relative;&quot;&gt;Do we really need container components?&lt;a href=&quot;#Do-we-really-need-container-components&quot; aria-label=&quot;Do we really need container components permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In 2019, with the advent of React hooks, &lt;a href=&quot;https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0&quot;&gt;Dan said we don&apos;t&lt;/a&gt;. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The main reason I found [container components] useful was because it let me separate complex stateful logic from other aspects of the component. Hooks let me do the same thing without an arbitrary division.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here are my thoughts.&lt;/p&gt;
&lt;p&gt;I fully agree that complex stateful logic &lt;strong&gt;shouldn&apos;t live within presentation components&lt;/strong&gt;. When we do that, we don&apos;t get the ability to reuse logic across different components. &lt;/p&gt;
&lt;p&gt;Now, as for stateful logic in &lt;em&gt;container components&lt;/em&gt;? I don&apos;t believe it &lt;em&gt;ever should have been in &apos;em.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Previously, React developers were advised to put data and behavior in container components and write code that determined &quot;how things work&quot;. That breaks the rules of what was said to be the responsibility of a container/presenter.&lt;/p&gt;
&lt;p&gt;Just because we know to put stateful data and behavior in React Hooks, it &lt;strong&gt;doesn&apos;t mean we removed the problems a container component solves&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;We &lt;em&gt;still&lt;/em&gt; need to configure &lt;em&gt;reactivity&lt;/em&gt;, sometimes using Redux, sometimes using Apollo Client or something else, and we &lt;em&gt;still&lt;/em&gt; need some construct to &lt;strong&gt;act as the glue, knowing which components to load up for the features we enable on a page&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Container-components-are-pages&quot; style=&quot;position:relative;&quot;&gt;Container components are pages&lt;a href=&quot;#Container-components-are-pages&quot; aria-label=&quot;Container components are pages permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the following React Router example, we have three main &lt;em&gt;pages:&lt;/em&gt; home, about, and dashboard. &lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;src/App.js&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Router&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Switch&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Route&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;exact&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt; 
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Home&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Route&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Route&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/about&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;About&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Route&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Route&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/dashboard&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Dashboard&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Route&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Switch&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Router&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Each page:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;is responsible for enable a variable number of features (remember, a feature is a &lt;code class=&quot;language-text&quot;&gt;command&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;query&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;has a variable number of presentational components within it, and&lt;/li&gt;
&lt;li&gt;knows about &lt;code class=&quot;language-text&quot;&gt;shared&lt;/code&gt; reactive state, and &lt;em&gt;sometimes&lt;/em&gt; connects it to presentational components that need it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Container components are the top-level modules that turn on all the features for a particular page. In Gatsby.js, we call them &lt;em&gt;Page components&lt;/em&gt;. Since all client architectures naturally evolve from this Model-View-Presenter pattern, it&apos;s unlikely we&apos;ll &lt;strong&gt;get rid of the presenter (container) entirely&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;To demonstrate my point, here&apos;s a &lt;em&gt;container component&lt;/em&gt; in a React hooks world. It might not look like much, but notice that &lt;strong&gt;it fulfills the two responsibilities of a container component&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;/modules/home/Home.container.tsx&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; MainSection &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../components/MainSection&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; useQuery &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@apollo/client&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; VisiblityFilter &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../models/VisibilityFilter&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Todos &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../models/Todos&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;GET_ALL_TODOS&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../operations/queries/getAllTodos&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;GET_VISIBILITY_FILTER&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../operations/queries/getVisibilityFilter&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; todoMutations &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../operations/mutations&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; todosAPI &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TodosAPI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Home&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Shared (global) or remote (global) state.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; operations&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; models &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useTodos&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todosAPI&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    completeAllTodos&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    setVisibilityFilter&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    clearCompletedTodos 
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; operations&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Layout&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      &amp;lt;MainSection
        // Pass data to components
        activeVisibilityFilter=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;visibilityFilter&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        todosCount=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;todos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        completedCount=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;todos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; t&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;completed&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
        
        // Delegate operations to the model
        actions=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          completeAllTodos&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          setVisibilityFilter&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          clearCompletedTodos
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
      /&gt;
      &amp;lt;ReportSection 
        // Pass data to components
        todos=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;todos&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;

        // Delegate operations to the model
        actions=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          completeAllTodos&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          setVisibilityFilter&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          clearCompletedTodos
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;
       /&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Layout&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Something&lt;/em&gt; is responsible for knowing how to connect to a reactive model, and knowing what to do with events that come from presentation components. That&apos;s a container.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Of course, you could call everything a &lt;em&gt;component,&lt;/em&gt; but then the explicit communication and delineation of responsibilities we&apos;re fighting for is lost.&lt;/p&gt;
&lt;h3 id=&quot;Container-components-contain-no-functionality&quot; style=&quot;position:relative;&quot;&gt;Container components contain no functionality&lt;a href=&quot;#Container-components-contain-no-functionality&quot; aria-label=&quot;Container components contain no functionality permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The container component is pretty bare. That&apos;s a good thing. They&apos;re not supposed to contain any functionality. They&apos;re not worthy of unit testing. They&apos;re just meant to stitch things together. However, if you want to do an integration test all features of a page, just load up the container component and have at &apos;er.&lt;/p&gt;
&lt;h2 id=&quot;Interaction-layer&quot; style=&quot;position:relative;&quot;&gt;Interaction layer&lt;a href=&quot;#Interaction-layer&quot; aria-label=&quot;Interaction layer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Model behavior&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We&apos;re finally in the most challenging part of a client-side architecture: the &lt;em&gt;model&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;The first layer of the model, which is what gets called from the container component, is the &lt;strong&gt;interaction layer&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Untitled%201.png&quot; alt=&quot;img/blog/client-side-architecture/Untitled%201.png&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;The-interaction-layer-is-the-behavior-of-the-model&quot; style=&quot;position:relative;&quot;&gt;The interaction layer is the behavior of the model&lt;a href=&quot;#The-interaction-layer-is-the-behavior-of-the-model&quot; aria-label=&quot;The interaction layer is the behavior of the model permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When you click submit to &quot;&lt;em&gt;add a todo&quot;&lt;/em&gt;, do you jump straight to the GraphQL &lt;code class=&quot;language-text&quot;&gt;mutation&lt;/code&gt; right away? Do you perform any validation logic? Are there any rules to enforce?&lt;/p&gt;
&lt;p&gt;A lot of times, there &lt;em&gt;aren&apos;t&lt;/em&gt; any rules. Sometimes we can&apos;t be bothered and we leave validation logic as something the &lt;em&gt;server&lt;/em&gt; handles. This is particularly common on simple dashboard apps. These apps have pretty much &lt;strong&gt;no rules to enforce&lt;/strong&gt;, so an interaction layer doesn&apos;t exist.&lt;/p&gt;
&lt;p&gt;It goes controller → network request. &lt;/p&gt;
&lt;p&gt;Or as we&apos;ve been doing for a long time, presentation component → network request.&lt;/p&gt;
&lt;p&gt;When there &lt;strong&gt;is&lt;/strong&gt; policy to enforce, it&apos;s time to think about carving out an interaction layer.&lt;/p&gt;
&lt;h3 id=&quot;The-interaction-layer-is-the-decision-making-layer&quot; style=&quot;position:relative;&quot;&gt;The interaction layer is the decision-making layer&lt;a href=&quot;#The-interaction-layer-is-the-decision-making-layer&quot; aria-label=&quot;The interaction layer is the decision making layer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Application (or interaction) logic&lt;/strong&gt; is the logic that makes a decision as to what happens next.&lt;/p&gt;
&lt;p&gt;Let&apos;s say you have a &lt;code class=&quot;language-text&quot;&gt;command&lt;/code&gt; called &lt;code class=&quot;language-text&quot;&gt;createTodoIfNotExists&lt;/code&gt;. Whatever construct is responsible for the interaction layer contains the code that helps you decide, &quot;should we follow through with this&quot;?&lt;/p&gt;
&lt;p&gt;Here&apos;s a &lt;a href=&quot;https://github.com/reduxjs/redux-thunk&quot;&gt;Redux Thunk&lt;/a&gt; example, where sometimes, we need to reach into some form of &lt;code class=&quot;language-text&quot;&gt;global&lt;/code&gt; state (maybe cached in a store) to make a decision.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;/todos/redux/thunks/createTodoIfNotExists.tsx&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Interaction example&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createTodoIfNotExists&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;text&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;dispatch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; getState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; todos &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; alreadyExists &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; todos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; t &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;alreadyExists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Validate&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Request&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Alternatively, here&apos;s a React Hooks &amp;#x26; Apollo Client example.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;/models/useTodos.tsx&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useTodos&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;todos&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;createTodoIfNotExists&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;text&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; alreadyExists &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; todos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; t &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;alreadyExists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Validate&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Request&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createTodoIfNotExists &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Container&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Main&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; todos &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;GET_ALL_TODOS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createTodoIfNotExists &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useTodos&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;todos&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;It-contains-your-applications-operations&quot; style=&quot;position:relative;&quot;&gt;It contains your application&apos;s operations&lt;a href=&quot;#It-contains-your-applications-operations&quot; aria-label=&quot;It contains your applications operations permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Some refer to this layer as &lt;strong&gt;app logic&lt;/strong&gt;, which works as well because these are all of the &lt;em&gt;operations&lt;/em&gt; of your app. The interaction layer contains the discrete set of &lt;code class=&quot;language-text&quot;&gt;commands&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;queries&lt;/code&gt; that your users will carry out. These are the &lt;em&gt;use cases&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Having great visibility into these &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt; enables us to get pretty structured with our integration testing as well. We can functionally test every use case with edge cases using Given-When-Then style tests.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Given&lt;/em&gt; no todos exist, &lt;em&gt;when&lt;/em&gt; I perform &lt;code class=&quot;language-text&quot;&gt;CreateTodo&lt;/code&gt;, &lt;em&gt;then&lt;/em&gt; I should see one todo.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Given&lt;/em&gt; I have 3 completed todos and 1 uncompleted one, &lt;em&gt;when&lt;/em&gt; I perform &lt;code class=&quot;language-text&quot;&gt;CompleteAllTodos&lt;/code&gt;, &lt;em&gt;then&lt;/em&gt; I should have 4 completed todos.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&apos;re familiar with &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design&lt;/a&gt; concepts, this is the &lt;a href=&quot;/articles/software-design-architecture/domain-driven-design-vs-clean-architecture/#Application-Services&quot;&gt;Application Service&lt;/a&gt; equivalent.&lt;/p&gt;
&lt;h3 id=&quot;Shared-behavior&quot; style=&quot;position:relative;&quot;&gt;Shared behavior&lt;a href=&quot;#Shared-behavior&quot; aria-label=&quot;Shared behavior permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This behavior is written to be used by any component. It contains the rules for how shared state is allowed to change. &lt;/p&gt;
&lt;p&gt;At this level, we&apos;re often handling concerns like &lt;code class=&quot;language-text&quot;&gt;auth&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;logging&lt;/code&gt;, or even more &lt;em&gt;domain-specific&lt;/em&gt; things like &lt;code class=&quot;language-text&quot;&gt;todos&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;users&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;calendar&lt;/code&gt;, or even &lt;code class=&quot;language-text&quot;&gt;chess&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Consider an interaction-layer React hook that contained all your chess game logic.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;/hooks/useChess.tsx&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useChess&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;todosAPI&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ITodosAPI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
   operations&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; makeMove&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isValidMove&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
   models&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; board&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; players&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; currentTurn &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Read &quot;&lt;a href=&quot;https://khalilstemmler.com/articles/graphql/ddd/schema-design/&quot;&gt;Domain-Driven GraphQL Schema Design&lt;/a&gt;&quot; for the principles and practices for how to use event Storming to discover the subdomains within your app.&lt;/p&gt;
&lt;h3 id=&quot;Other-ways-to-implement-the-model&quot; style=&quot;position:relative;&quot;&gt;Other ways to implement the model&lt;a href=&quot;#Other-ways-to-implement-the-model&quot; aria-label=&quot;Other ways to implement the model permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Though most React developers will be comfortable writing their application/interaction layer logic using something like React Hooks, there&apos;s tons of other ways to implement the model. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you like to think of your model as a state machine, the &lt;a href=&quot;https://xstate.js.org/docs/recipes/react.html#hooks&quot;&gt;xState library&lt;/a&gt; does this exceptionally well and provides capabilities for you to plug your model instance into a React hook.&lt;/li&gt;
&lt;li&gt;For those who want to try to model their interaction layer using plain vanilla JavaScript, the &lt;a href=&quot;https://github.com/xolvio/pojo-observer&quot;&gt;pojo-observer library&lt;/a&gt; takes advantage of the fact that every client-app is an implementation of the observer pattern. Separating your model code from React hooks, it also provides a way to notify React that the model changed so a re-render is necessary.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Someone once asked me &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/ddd-frontend/&quot;&gt;if it&apos;s possible to do DDD in the front-end&lt;/a&gt;. Initially, I said &lt;em&gt;no&lt;/em&gt;, but after sometime thinking about it, it &lt;em&gt;totally is&lt;/em&gt;. While the true high-level policy will always live on the backend, the interaction layer is comparable to the Application and &lt;em&gt;possibly&lt;/em&gt; Domain layer in DDD.&lt;/p&gt;
&lt;h3 id=&quot;There-are-usually-several-layers&quot; style=&quot;position:relative;&quot;&gt;There are usually several layers&lt;a href=&quot;#There-are-usually-several-layers&quot; aria-label=&quot;There are usually several layers permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Most of the time, your app will have several of these &lt;strong&gt;application / interaction&lt;/strong&gt; layers.&lt;/p&gt;
&lt;p&gt;Here are some more examples of interaction layers that are commonly built out.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Examples of other interaction layers&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Auth layer — Extremely common. Check out the &lt;a href=&quot;https://github.com/Swizec/useAuth&quot;&gt;useAuth&lt;/a&gt; library which implements Auth0 authentication and authorization as a React hook.&lt;/li&gt;
&lt;li&gt;Logging — Sometimes it&apos;s important to. Luckily, there are many tools out there that can do this for you, but if you needed to build one yourself, it would exist as an entirely separate layer within your model.&lt;/li&gt;
&lt;li&gt;Real-time subscriptions — Let&apos;s say you&apos;re subscribed to a stream of data. When a chunk comes in, you need to process it, and perhaps act on a &lt;code class=&quot;language-text&quot;&gt;switch&lt;/code&gt; statement to figure out if you should invoke a &lt;code class=&quot;language-text&quot;&gt;command&lt;/code&gt;. Keep your code clean by delegating this responsibility to a layer.&lt;/li&gt;
&lt;li&gt;Complex rendering logic — I once worked on a project that built out really complex call flows for call centers using Angular and D3. Hundreds of different node types could be dragged and dropped onto a surface. When dropped, the way they connected to each other and how they could be used depended on the rendering and application logic, each decoupled from each other.&lt;/li&gt;
&lt;li&gt;Metadata layer — Imagine building a multiplayer video game where new prizes and weapons come out every week. How can we prevent hard-coding weapons and prizes?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&apos;re curious about what a large-scale version of this looks like, check out &lt;a href=&quot;https://github.com/twilio/twilio-video-app-react&quot;&gt;Twilio&apos;s video-app example&lt;/a&gt; built with React hooks and context for global state.&lt;/p&gt;
&lt;h2 id=&quot;-Networking--data-fetching-infrastructure&quot; style=&quot;position:relative;&quot;&gt;🚡 Networking &amp;#x26; data fetching (infrastructure)&lt;a href=&quot;#-Networking--data-fetching-infrastructure&quot; aria-label=&quot; Networking  data fetching infrastructure permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Performing API calls and reporting metadata state&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The responsibilities of a networking and data fetching layer are to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Know where the backend service(s) are&lt;/li&gt;
&lt;li&gt;Formulate responses&lt;/li&gt;
&lt;li&gt;Marshal response data or errors&lt;/li&gt;
&lt;li&gt;Report async statuses (isLoading)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Untitled%201.png&quot; alt=&quot;img/blog/client-side-architecture/Untitled%201.png&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Reporting-metadata-state&quot; style=&quot;position:relative;&quot;&gt;Reporting metadata state&lt;a href=&quot;#Reporting-metadata-state&quot; aria-label=&quot;Reporting metadata state permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Jed Watson describes the async states that tell you about the status of a network request as &lt;strong&gt;meta state&lt;/strong&gt; — state &lt;em&gt;about&lt;/em&gt; state.&lt;/p&gt;
&lt;p&gt;For example, in Apollo Client, the &lt;code class=&quot;language-text&quot;&gt;loading&lt;/code&gt; variable we deconstruct from the query response is a form of meta state.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; loading&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;GET_ALL_TODOS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With Apollo Client, that&apos;s handled for us. Though if we were to use a more barebones approach, like Axios and Redux, we&apos;d have to write this signaling code ourselves within a Thunk.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createTodoIfNotExists&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;text&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;dispatch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; getState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; todos &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; alreadyExists &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; todos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; t &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;alreadyExists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
     
    &lt;span class=&quot;token comment&quot;&gt;// Signaling start&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; actions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;CREATING_TODO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; todoAPI&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      
      &lt;span class=&quot;token comment&quot;&gt;// Signaling success&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; actions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;CREATING_TODO_SUCCESS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; todo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;todo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  
      &lt;span class=&quot;token comment&quot;&gt;// Signaling Failure&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; actions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;CREATING_TODO_FAILURE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; err &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Note&lt;/b&gt;: The code example above is a demonstration of doing a little too much. Recall that a Redux Thunk is an interaction layer concern? That means it should &lt;i&gt;only&lt;/i&gt; be responsible for the decision-making logic, and no &lt;i&gt;signalling&lt;/i&gt; logic, since request signalling is a concern of the networking &amp; data-fetching layer. It can be hard to establish these concrete boundaries sometimes. Especially if the library or framework wasn&apos;t designed with separation of concerns in mind.&lt;/p&gt;
&lt;h2 id=&quot;️-State-management--storage-infrastructure&quot; style=&quot;position:relative;&quot;&gt;🗄️ State management &amp;#x26; storage (infrastructure)&lt;a href=&quot;#%EF%B8%8F-State-management--storage-infrastructure&quot; aria-label=&quot;️ State management  storage infrastructure permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Storage, updating data, reactivity&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A state management library has &lt;em&gt;three&lt;/em&gt; responsibilities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Storage&lt;/strong&gt; — Hold onto global state somewhere, usually in a store / client-side cache.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Updating data&lt;/strong&gt; — Make changes to the data in the cache.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reactivity&lt;/strong&gt;  — Provide a way for view-layer presentation components to subscribe to data, and then re-render when data changes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;State-management-and-networking-are-often-solved-together&quot; style=&quot;position:relative;&quot;&gt;State management and networking are often solved together&lt;a href=&quot;#State-management-and-networking-are-often-solved-together&quot; aria-label=&quot;State management and networking are often solved together permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;State management is complex. &lt;/p&gt;
&lt;p&gt;Because it&apos;s complex, there are libraries out there to make life a little bit easier. Two of those libraries, Apollo Client and react-query, actually handle the &lt;em&gt;networking&lt;/em&gt; part for you.&lt;/p&gt;
&lt;p&gt;It can be preferable to choose a library instead of building out the state management machinery and &lt;em&gt;networking&lt;/em&gt; layer manually.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/Untitled%202.png&quot; alt=&quot;img/blog/client-side-architecture/Untitled%202.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Apollo Client handles both the state management and data fetching concerns.&lt;/p&gt;
&lt;h3 id=&quot;Shared-global-state&quot; style=&quot;position:relative;&quot;&gt;Shared global state&lt;a href=&quot;#Shared-global-state&quot; aria-label=&quot;Shared global state permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Two types of state exist at this layer. They are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;remote (global)&lt;/code&gt; state — The state that exists behind APIs in services. When we make &lt;code class=&quot;language-text&quot;&gt;queries&lt;/code&gt; for remote state, we hold onto a local copy of it accessible from a global scope.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;shared (global)&lt;/code&gt; : We said earlier, &quot;as soon as some state belongs to more than one component, it&apos;s &lt;em&gt;shared&lt;/em&gt; global state&quot;. And you&apos;ll know you need this when &lt;strong&gt;two components that rely on the same state don&apos;t need to know about each other&lt;/strong&gt;. To be clear, this type of state can be live in the interaction layer (via hooks and context, for example). Though sometimes, when working with &lt;code class=&quot;language-text&quot;&gt;remote(global) state&lt;/code&gt;, it&apos;s preferable to have something act as a single source of truth, especially if you need to mix remote and local state.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Mixture-of-remote-and-local-state&quot; style=&quot;position:relative;&quot;&gt;Mixture of remote and local state&lt;a href=&quot;#Mixture-of-remote-and-local-state&quot; aria-label=&quot;Mixture of remote and local state permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We often cache remote state in a client-side cache or store. Since we do that, it&apos;s reasonable to try to use the store as a single source of truth. Often, we&apos;d like to add some client-only local variables or pieces of state to the store as well.&lt;/p&gt;
&lt;p&gt;Here&apos;s a Redux example of adding an &lt;code class=&quot;language-text&quot;&gt;isSelected&lt;/code&gt; attribute to each of the &lt;code class=&quot;language-text&quot;&gt;todos&lt;/code&gt; before merging to the store.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;action&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; actions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;GET_TODOS_SUCCESS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Add some local state to the remote state before merging it&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// to the store&lt;/span&gt;
      todos&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; action&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;todos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isSelected&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And in Apollo Client 3, here&apos;s the equivalent with cache policies and reactive variables. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;jsx&quot;&gt;&lt;pre class=&quot;language-jsx&quot;&gt;&lt;code class=&quot;language-jsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; InMemoryCache &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@apollo/client&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cache&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; InMemoryCache &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InMemoryCache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  typePolicies&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Todo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      fields&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        isSelected&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; opts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; todoId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; opts&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isSelected &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;currentSelectedTodoIds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; id &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; todoId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
              
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; isSelected&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; currentSelectedTodoIds &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;makeVar&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;number&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can configure a way to request &lt;code class=&quot;language-text&quot;&gt;remote&lt;/code&gt; state and &lt;em&gt;client-only&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;shared&lt;/code&gt; local state in the same query.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;GET_ALL_TODOS&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; gql&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
  query GetAllTodos {
    todos { 
      id  
      text  
      completed
      isSelected @client
    }
  }
&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Storage-facades&quot; style=&quot;position:relative;&quot;&gt;Storage facades&lt;a href=&quot;#Storage-facades&quot; aria-label=&quot;Storage facades permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Most of the time we don&apos;t provide direct access to whats stored within the &lt;em&gt;store&lt;/em&gt;. Usually, there&apos;s some &lt;em&gt;facade&lt;/em&gt;, an API, that sits in-front of the data and provides ways for us to interact with it.&lt;/p&gt;
&lt;p&gt;In Redux, this is &lt;code class=&quot;language-text&quot;&gt;dispatch&lt;/code&gt; (for updates) and connect (for reactivity).&lt;/p&gt;
&lt;p&gt;In Apollo Client, this is &lt;code class=&quot;language-text&quot;&gt;useMutation&lt;/code&gt; (for updates) and &lt;code class=&quot;language-text&quot;&gt;useQuery&lt;/code&gt; (for reactivity).&lt;/p&gt;
&lt;p&gt;Even SQL is a form of a storage facade. It&apos;s a powerful pattern.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/client-side-architecture/storage__facades.png&quot; alt=&quot;img/blog/client-side-architecture/storage__facades.png&quot;&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[The Three Responsibilities of a Client-Side State Management Solution]]></title><description><![CDATA[Historically, when starting on a new React project, we’ve had to design and implement the state management infrastructure from scratch in a…]]></description><link>https://khalilstemmler.com/blogs/software-design/three-responsibilities-client-side-state-management/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/software-design/three-responsibilities-client-side-state-management/</guid><pubDate>Thu, 14 May 2020 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Historically, when starting on a new React project, we’ve had to design and implement the state management infrastructure from scratch in a bare-bones way.&lt;/p&gt;
&lt;p&gt;No matter which approach we take, in every client-side application, the generic role of a state management solution is the same: to handle storage, update state, and enable Reactivity.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/responsibilities-state-management/client-side-responsibilities.png&quot; alt=&quot;Client-side state management&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;Storage&quot; style=&quot;position:relative;&quot;&gt;Storage&lt;a href=&quot;#Storage&quot; aria-label=&quot;Storage permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most apps need to hold onto some data. That data may contain a little slice of &lt;strong&gt;local state&lt;/strong&gt; that we’ve configured client-side, or it could be a subset of &lt;strong&gt;remote state&lt;/strong&gt; from our backend services.&lt;/p&gt;
&lt;p&gt;Often, we need to combine these two pieces of data, local and remote, and then call upon them in our app at the same time. This task alone has the potential to get pretty complicated, especially when we need to perform &lt;strong&gt;updates to the state&lt;/strong&gt; of our app.&lt;/p&gt;
&lt;h2 id=&quot;Update-state&quot; style=&quot;position:relative;&quot;&gt;Update state&lt;a href=&quot;#Update-state&quot; aria-label=&quot;Update state permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://khalilstemmler.com/articles/oop-design-principles/command-query-segregation/&quot;&gt;Command-Query Segregation Principle&lt;/a&gt; states that there are two generic types of operations we can perform: &lt;code class=&quot;language-text&quot;&gt;commands&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;queries&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In GraphQL, we refer to these as &lt;code class=&quot;language-text&quot;&gt;queries&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;mutations&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In REST, we have several &lt;code class=&quot;language-text&quot;&gt;command&lt;/code&gt;-like operations like &lt;code class=&quot;language-text&quot;&gt;delete&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;update&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;post&lt;/code&gt;, etc and one &lt;code class=&quot;language-text&quot;&gt;query&lt;/code&gt;-like operation called &lt;code class=&quot;language-text&quot;&gt;get&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Most of the time, after invoking an operation in a client-side web app, we need to update the state stored locally as a side-effect.&lt;/p&gt;
&lt;h2 id=&quot;Reactivity&quot; style=&quot;position:relative;&quot;&gt;Reactivity&lt;a href=&quot;#Reactivity&quot; aria-label=&quot;Reactivity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When storage changes, we need an effective way to notify pieces of our UI that relied on that particular part of the store, and that they should present the new data.&lt;/p&gt;
&lt;h2 id=&quot;Each-state-management-approach-has-a-slightly-different-approach&quot; style=&quot;position:relative;&quot;&gt;Each state management approach has a slightly different approach&lt;a href=&quot;#Each-state-management-approach-has-a-slightly-different-approach&quot; aria-label=&quot;Each state management approach has a slightly different approach permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Just about every library available out there right now can adequately handle all three of these responsibilities! Here are some of the most popular approaches right now in the React realm.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/responsibilities-state-management/state-management-options.png&quot; alt=&quot;Client-side state management options&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Redux&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Storage: Plain JS object&lt;/li&gt;
&lt;li&gt;Updating state: actions + reducers&lt;/li&gt;
&lt;li&gt;Reactivity: Connect&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;React Context + Hooks&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Storage: Plain JS object&lt;/li&gt;
&lt;li&gt;Updating state: useReducer (or not)&lt;/li&gt;
&lt;li&gt;Reactivity: useContext&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Apollo Client&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Storage: Normalized cache&lt;/li&gt;
&lt;li&gt;Updating state: Cache APIs&lt;/li&gt;
&lt;li&gt;Reactivity: (Auto) Broadcast change notifications to Queries&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Accidental and Essential Complexity]]></title><description><![CDATA[Ever seen a friend, coworker, or maybe even an accidental stranger- trying to solve a problem using a tool that you feel is completely unfit…]]></description><link>https://khalilstemmler.com/articles/software-professionalism/absolute-and-relative-complexity/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/software-professionalism/absolute-and-relative-complexity/</guid><pubDate>Wed, 29 Apr 2020 15:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;special-quote&quot;&gt;🌱 This blog post hasn&apos;t fully bloomed. It&apos;s very likely to change over the next little while because it&apos;s a little bit flawed. In fact, an old version of this post was titled &quot;Absolute and Relative complexity&quot;. I then discovered that Ben Moseley wrote a famous paper written about this very phenomenon called, &quot;Accidental and Essential Complexity&quot;. I&apos;m re-writing this post to build on top of the existing philosophy using the terminology expressed there. The most up-to-date writing I have on this at the moment is in &quot;&lt;a target=&quot;_blank&quot; href=&quot;https://wiki.solidbook.io/1-Complexity-&amp;-the-World-of-Software-Design-89c30351edc748b78655b6122dc81710&quot;&gt;Chapter 1 - Complexity &amp; The World of Software Design&lt;/a&gt;&quot; from &lt;a target=&quot;_blank&quot; href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt;. This will eventually catch up&lt;/p&gt;
&lt;p&gt;Ever seen a friend, coworker, or maybe even an accidental stranger- trying to solve a problem using a tool that you feel is &lt;em&gt;completely unfit&lt;/em&gt; for the task at hand? &lt;/p&gt;
&lt;p&gt;Maybe you&apos;ve felt like a problem would be easier solved using a different tool, language, platform, or feature for the job.&lt;/p&gt;
&lt;p&gt;It&apos;s frustrating. It&apos;s frustrating seeing someone introduce undue &lt;em&gt;challenge&lt;/em&gt; for themselves when you feel like you know there&apos;s a better way.&lt;/p&gt;
&lt;p&gt;In discussions about architecture, choosing a tech stack, and solving problems in general, I&apos;ve started to use the terms &quot;accidental complexity&quot; and &quot;essential complexity&quot; more often. Maybe you will too.&lt;/p&gt;
&lt;p&gt;Being able to point out accidental and essential complexity will enable you to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Decide &lt;a href=&quot;/articles/when-to-use-typescript-guide/&quot;&gt;when it&apos;s a good idea to use TypeScript over JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Know when to use &lt;a href=&quot;/articles/categories/domain-driven-design/&quot;&gt;Domain-Driven Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Avoid anti-patterns&lt;/li&gt;
&lt;li&gt;Know when you&apos;re tackling a problem using well-known best practices or introducing more challenge for yourself&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Essential-complexity&quot; style=&quot;position:relative;&quot;&gt;Essential complexity&lt;a href=&quot;#Essential-complexity&quot; aria-label=&quot;Essential complexity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Essential complexity&lt;/b&gt;: When the complexity of the problem is related to the &lt;i&gt;nature&lt;/i&gt; of the problem itself.&lt;/p&gt;
&lt;p&gt;Let&apos;s face it. Some things in life are just inherently complex.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Making a &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;vinyl-trading platform&lt;/a&gt; with lots of very specific domain-knowledge.&lt;/li&gt;
&lt;li&gt;Architecting and constructing a house from scratch.&lt;/li&gt;
&lt;li&gt;Using AI to write catchy pop music.&lt;/li&gt;
&lt;li&gt;Coming up with a cure for cancer.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There&apos;s no &lt;em&gt;easy&lt;/em&gt; answer to any of these things. Some of them don&apos;t even &lt;em&gt;have&lt;/em&gt; an answer. &lt;/p&gt;
&lt;p&gt;Often times though, we have a &lt;strong&gt;best practice&lt;/strong&gt;. And a best practice acts as a &lt;em&gt;close enough&lt;/em&gt; or the best that we can possibly do today. Best practices have considered all of the current options, and decided upon what the best approach is. Best practices are usually agreed upon by a larger community.&lt;/p&gt;
&lt;p&gt;Here&apos;s an easy one.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;best practice&lt;/strong&gt; for tying your shoes is to use your hands to tie your shoes into a knot. That&apos;s probably the easiest and &lt;em&gt;most realistic&lt;/em&gt; way to tie our shoes, because well- mini robot butlers aren&apos;t really a thing yet. A way to make life &lt;em&gt;harder&lt;/em&gt; and introduce &lt;strong&gt;accidental complexity&lt;/strong&gt; is to force yourself to tie your shoes using only a pair of chopsticks, never touching your shoelaces with your hands.&lt;/p&gt;
&lt;h2 id=&quot;Accidental-complexity&quot; style=&quot;position:relative;&quot;&gt;Accidental complexity&lt;a href=&quot;#Accidental-complexity&quot; aria-label=&quot;Accidental complexity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Accidental complexity&lt;/b&gt;: When the complexity of solving the problem is directly related to &lt;i&gt;the way that we have chosen to solve it&lt;/i&gt;, and less related to the nature of the problem itself.&lt;/p&gt;
&lt;p&gt;When we take an approach to solving a problem that &lt;strong&gt;introduces more work or complexity for us&lt;/strong&gt;, if not immediately, later on down the road, that&apos;s accidental complexity.&lt;/p&gt;
&lt;p&gt;We don&apos;t often introduce accidental complexity purposefully. In software, sometimes it comes up when we:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Want to use a brand new programming language or tool to solve a project that it is not well-suited for&lt;/li&gt;
&lt;li&gt;Are forced to use a particular tech stack&lt;/li&gt;
&lt;li&gt;Are unaware of the best practices to solving this particular problem (and in turn, implement an anti-pattern)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Accidental-complexity-is-introduced-by-failing-to-use-best-practices&quot; style=&quot;position:relative;&quot;&gt;Accidental complexity is introduced by failing to use best practices&lt;a href=&quot;#Accidental-complexity-is-introduced-by-failing-to-use-best-practices&quot; aria-label=&quot;Accidental complexity is introduced by failing to use best practices permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When I was working on my first startup, I wrote the entire thing in vanilla Node.js. Over time, we started to get more and more business logic complexity added to the app. Eventually, I found myself in a position where it was impossible for me to add new code without breaking old stuff.&lt;/p&gt;
&lt;p&gt;It was a huge mess because I had designed it &lt;a href=&quot;/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;with CRUD &amp;#x26; MVC&lt;/a&gt; (also known as a Transaction Script) where the problem really needed a more robust solution. &lt;/p&gt;
&lt;p&gt;In this scenario, the challenge was to &lt;strong&gt;build a large-scale business logic-heavy enterprise application&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The best practices for that task are to use Domain-Driven Design, separate your concerns using the clean/hexagonal architecture, write tests, and implement design patterns when necessary.&lt;/p&gt;
&lt;p&gt;It turns out that doing all of these things with JavaScript &lt;em&gt;is hard&lt;/em&gt;. Harder than it needs to be. There are several reasons why, and I explain why in detail &lt;a href=&quot;/articles/when-to-use-typescript-guide/&quot;&gt;here&lt;/a&gt;, but ultimately, it&apos;s the lack of a language concept to express &lt;strong&gt;abstractions&lt;/strong&gt; (interfaces and abstract classes). Without abstractions and a type system, implementing &lt;em&gt;contractual software design&lt;/em&gt; is harder in JavaScript.&lt;/p&gt;
&lt;p&gt;That was the main reason why I made the move to TypeScript for that project; because the best practices for a large-scale business logic-heavy enterprise application were easier to implement in TypeScript than in JavaScript.&lt;/p&gt;
&lt;p&gt;Yes, it was a challenge to learn and migrate to TypeScript. But that challenge was guided towards implementing the best practices that the problem afforded. Not all projects have the same needs as a large-scale enterprise app.&lt;/p&gt;
&lt;h2 id=&quot;Sometimes-best-practices-are-a-lot-of-work&quot; style=&quot;position:relative;&quot;&gt;Sometimes best practices are a lot of work&lt;a href=&quot;#Sometimes-best-practices-are-a-lot-of-work&quot; aria-label=&quot;Sometimes best practices are a lot of work permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&apos;m not gonna lie. Writing testable code, using DDD, and clean architecture is a lot of work. But if you&apos;re working on a project that needs that, &lt;a href=&quot;/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;and you&apos;re able to identify that&lt;/a&gt;, then it&apos;s the best path we have to the &lt;em&gt;right&lt;/em&gt; way to do things.&lt;/p&gt;
&lt;img src=&quot;/img/wiki/anemic/chart.svg&quot;/&gt;
&lt;h2 id=&quot;Anti-patterns-can-introduce-essential-complexity&quot; style=&quot;position:relative;&quot;&gt;Anti-patterns can introduce essential complexity&lt;a href=&quot;#Anti-patterns-can-introduce-essential-complexity&quot; aria-label=&quot;Anti patterns can introduce essential complexity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the evolution of bad code, it starts with &lt;em&gt;code smells&lt;/em&gt;. Code smells are indications that something might be wrong with the way we&apos;ve designed our code and that we should probably take a better look at it. &lt;/p&gt;
&lt;p&gt;That&apos;s the first step towards bad code, and it&apos;s not purposeful. These things just happen sometimes. If we can catch it, that&apos;s great. We can refactor and clean up code before it becomes a problem.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Wait. Why would we need to pass in a &quot;logger&quot; object to create a user?&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// A logger is an &quot;infrastructural&quot; cross-cutting concern, and it definitely &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// doesn&apos;t belong in our user factory method.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Also, this parameter list will only increase as we add more things to create&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// the user. We should use an object instead.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt;  &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; logger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;An anti-pattern, however, is a little bit more aggressive. An anti-pattern is deliberate approach to solving a problem in a way that &lt;strong&gt;goes against best practices&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Anti-patterns have the potential to introduce &lt;em&gt;essential complexity&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Anti-pattern-example-Duck-typing-with-JavaScript&quot; style=&quot;position:relative;&quot;&gt;Anti-pattern example: Duck-typing with JavaScript&lt;a href=&quot;#Anti-pattern-example-Duck-typing-with-JavaScript&quot; aria-label=&quot;Anti pattern example Duck typing with JavaScript permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: To prevent developers from passing in invalid objects.&lt;/p&gt;
&lt;p&gt;Let&apos;s say that we want to create slugs for blog posts using the following function.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Returns a slug like: &quot;2020/02/12/accidental-complexity-212312&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createSlug&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createDateString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postedDate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt; 
    &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createSlugFromTitle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-&quot;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createRandomNumber&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The function expects that we&apos;re going to pass in a &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt; object that has  &lt;code class=&quot;language-text&quot;&gt;postedDate&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;title&lt;/code&gt; attributes.&lt;/p&gt;
&lt;p&gt;But developers keep on passing in the &lt;em&gt;title&lt;/em&gt; of the post as a &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; post &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Accidental and Essential Complexity&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; slug &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createSlug&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ERROR&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is a silly problem. But on projects that are substantially large, it&apos;s pretty common to see. Especially if you&apos;re not familiar with the entire codebase.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Essential complexity&lt;/strong&gt;: Need to signal to clients that use the API that the method requires a post object with &lt;code class=&quot;language-text&quot;&gt;postedDate&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;title&lt;/code&gt;, and enforce that.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Accidental complexity&lt;/strong&gt;: Using JavaScript,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For API clients, you need to know the internals of every method. You can&apos;t rely on &lt;a href=&quot;/articles/typescript-domain-driven-design/intention-revealing-interfaces/&quot;&gt;intention revealing interfaces&lt;/a&gt; alone.&lt;/li&gt;
&lt;li&gt;For API authors, you need to use duck-typing and throw errors.&lt;/li&gt;
&lt;li&gt;For API authors, you need to write more comments so that developers know how to use the API. The function signature is not enough to express valid use.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/**
 * @desc Creates a slug. You need to pass in a post object with `postedDate`
 * and `title` to create it.
 */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createSlug&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postedDate &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isADate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postedDate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Need to provide a post object with date as &apos;postedDate&apos;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Need to provide a post object with a string title.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Also, we would need to include the post title&apos;s validation logic here as well&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// which may include making sure that the title is a certain length.&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createDateString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postedDate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt; 
    &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createSlugFromTitle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-&quot;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createRandomNumber&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Best practice solutions&lt;/strong&gt;: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use a statically-typed language to indicate and enforce valid API usage.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createSlug&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;post&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createDateString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postedDate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt; 
    &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createSlugFromTitle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-&quot;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createRandomNumber&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;!-- 
### Anti-pattern example: Configuration as source code

### Anti-pattern example: Vendor lock-in

Lets say you&apos;ve built an entire application on top of a hot new platform, used their APIs have intertwined your rich business logic with vendor-specific details.

Suddenly they decide to start charging users at a price point you&apos;re not willing to pay.

**Challenge**: Switching vendors
**Accidental complexity**: 
**Essential complexity**: We have to go through all of our code, replace any references to the expensive vendor&apos;s APIs with the new vendor, and make sure that everything still works. --&gt;
&lt;h2 id=&quot;Breaking-best-practices-and-implementing-anti-patterns&quot; style=&quot;position:relative;&quot;&gt;Breaking best practices and implementing anti-patterns&lt;a href=&quot;#Breaking-best-practices-and-implementing-anti-patterns&quot; aria-label=&quot;Breaking best practices and implementing anti patterns permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Implementing best practices and avoiding anti-patterns will get us where we need to go in the long run, but will often require some more upfront work.&lt;/p&gt;
&lt;p&gt;I think it&apos;s occasionally OK to &lt;strong&gt;break best practices&lt;/strong&gt; and &lt;strong&gt;implement anti-patterns&lt;/strong&gt; in order to go a little faster. &lt;/p&gt;
&lt;p&gt;I give it my blessing in one condition...&lt;/p&gt;
&lt;p&gt;Know what the rules (best practices) are &lt;em&gt;before&lt;/em&gt; you decide to break &apos;em.&lt;/p&gt;
&lt;p&gt;I take shortcuts all the time. But I try to always know what the implications are first.&lt;/p&gt;
&lt;h2 id=&quot;Resources&quot; style=&quot;position:relative;&quot;&gt;Resources&lt;a href=&quot;#Resources&quot; aria-label=&quot;Resources permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;No-Silver-Bullets---Accidental-and-Essential-Complexity&quot; style=&quot;position:relative;&quot;&gt;No Silver Bullets - Accidental and Essential Complexity&lt;a href=&quot;#No-Silver-Bullets---Accidental-and-Essential-Complexity&quot; aria-label=&quot;No Silver Bullets   Accidental and Essential Complexity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Shortly after this post was released to the interwebs, someone kindly pointed me to the &quot;&lt;a href=&quot;https://en.wikipedia.org/wiki/No_Silver_Bullet&quot;&gt;No Silver Bullet – Essence and Accident in Software Engineering&lt;/a&gt;&quot; Wikipedia page. Funny. The fact that I had arrived at the concept of &lt;em&gt;accidental&lt;/em&gt; and &lt;em&gt;essential&lt;/em&gt; complexity myself, yet was already well-researched and discussed as &lt;em&gt;essential&lt;/em&gt; and &lt;em&gt;accidental&lt;/em&gt; complexity, reinforces the following statement:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Not a lot has changed about the fundamentals of software design over the past 20 years, but there&apos;s a huge lack of training on it&quot; - me, via &lt;a href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you&apos;re interested in learning more about this subject, I suggest checking out this paper called &quot;&lt;a href=&quot;http://curtclifton.net/papers/MoseleyMarks06a.pdf?fbclid=IwAR0hFwqsdQxwSyv8ayiQsOjET3aYQDm33dMeSXgcZHfDmqI4Cfmwo4hAKfc&quot;&gt;Out of the Tar Pit&lt;/a&gt;&quot; by Ben Moseley.&lt;/p&gt;
&lt;p&gt;It builds on top of the classic paper about software complexity originally discussed by Fred Brooks in 1986. It&apos;s very well put together and worth your time. Consider reading the first half at least.&lt;/p&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In summary, ask yourself if the problem is hard because it&apos;s a &lt;em&gt;hard&lt;/em&gt; problem, or if you&apos;re &lt;em&gt;making&lt;/em&gt; it hard by not following best practices.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Enforcing Coding Conventions with Husky Pre-commit Hooks]]></title><description><![CDATA[Intro On most projects I've ever worked collaboratively on, someone takes the role of the code cleanliness champion. It's usually the team…]]></description><link>https://khalilstemmler.com/blogs/tooling/enforcing-husky-precommit-hooks/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/tooling/enforcing-husky-precommit-hooks/</guid><pubDate>Tue, 10 Mar 2020 15:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;special-quote&quot;&gt;This post is a part of the &lt;b&gt;Clean Code Tooling&lt;/b&gt; series. &lt;br/&gt;You may want to read the previous posts.&lt;br/&gt;&lt;a href=&quot;/blogs/typescript/eslint-for-typescript/&quot;&gt;1. How to use ESLint with TypeScript&lt;/a&gt;&lt;br/&gt;&lt;a href=&quot;/blogs/tooling/prettier/&quot;&gt;2. How to use Prettier with ESLint and TypeScript in VSCode&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;Intro&quot; style=&quot;position:relative;&quot;&gt;Intro&lt;a href=&quot;#Intro&quot; aria-label=&quot;Intro permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;On most projects I&apos;ve ever worked collaboratively on, &lt;em&gt;someone&lt;/em&gt; takes the role of the &lt;em&gt;code cleanliness champion&lt;/em&gt;. It&apos;s usually the team lead, and often times, their role involves reviewing &lt;a href=&quot;https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests&quot;&gt;PRs&lt;/a&gt; and making sure love and care is put into the quality of the code.&lt;/p&gt;
&lt;p&gt;Quality includes both the chosen &lt;strong&gt;coding conventions&lt;/strong&gt; in addition to the &lt;strong&gt;formatting&lt;/strong&gt; of the code.&lt;/p&gt;
&lt;p&gt;Today, it&apos;s good practice in JavaScript projects to utilize &lt;a href=&quot;/blogs/typescript/eslint-for-typescript/&quot;&gt;ESLint&lt;/a&gt; to define the project&apos;s coding conventions. For example, how does your team feel about using &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; loops? What about semicolons- are those required? Etc.&lt;/p&gt;
&lt;p&gt;Those are conventions.&lt;/p&gt;
&lt;p&gt;The other piece of the puzzle is formatting. That&apos;s the &lt;em&gt;visual appearance&lt;/em&gt; of the code. When there&apos;s more than one developer working on a project, ensuring that code &lt;em&gt;looks&lt;/em&gt; consistent is something to be addressed.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/blogs/tooling/prettier/&quot;&gt;Prettier&lt;/a&gt; is the correct tool for this.&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&quot;/blogs/tooling/prettier/&quot;&gt;previous article&lt;/a&gt;, we learned how to combine both ESLint and Prettier, but we didn&apos;t learn how to actually &lt;strong&gt;enforce&lt;/strong&gt; the conventions and formatting on a real life project with multiple developers.&lt;/p&gt;
&lt;p&gt;In this article, we&apos;ll learn how to use &lt;a href=&quot;https://github.com/typicode/husky&quot;&gt;Husky&lt;/a&gt; to do so on a Git-based project.&lt;/p&gt;
&lt;h2 id=&quot;Husky&quot; style=&quot;position:relative;&quot;&gt;Husky&lt;a href=&quot;#Husky&quot; aria-label=&quot;Husky permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Husky is an npm package that &quot;makes Git hooks easy&quot;.&lt;/p&gt;
&lt;p&gt;When you initialize &lt;a href=&quot;https://git-scm.com/&quot;&gt;Git&lt;/a&gt; (the version control tool that you&apos;re probably familar with) on a project, it automatically comes with a feature called &lt;strong&gt;hooks&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If you go to the root of a project intialized with Git and type:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; .git/hooks&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You&apos;ll see a list of sample hooks like &lt;code class=&quot;language-text&quot;&gt;pre-push&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;pre-rebase&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;pre-commit&lt;/code&gt;, and so on. This is a way for us to write plugin code to execute some logic &lt;em&gt;before&lt;/em&gt; we perform the action.&lt;/p&gt;
&lt;p&gt;If we wanted to ensure &lt;strong&gt;before someone creates a commit&lt;/strong&gt; using the &lt;code class=&quot;language-text&quot;&gt;git commit&lt;/code&gt; command, that their code was properly linted and formatted, we could write a &lt;code class=&quot;language-text&quot;&gt;pre-commit&lt;/code&gt; Git hook.&lt;/p&gt;
&lt;p&gt;Writing that &lt;em&gt;manually&lt;/em&gt; probably wouldn&apos;t be fun. It would also be a challenge to distribute and ensure that hooks were installed on other developers&apos; machines.&lt;/p&gt;
&lt;p&gt;These are some of the challenges that Husky aims to address.&lt;/p&gt;
&lt;p&gt;With Husky, we can ensure that for a new developer working in our codebase (using at least Node version 10):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hooks get created locally&lt;/li&gt;
&lt;li&gt;Hooks are run when the Git command is called&lt;/li&gt;
&lt;li&gt;Policy that defines &lt;em&gt;how&lt;/em&gt; someone can contribute to a project is enforced.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&apos;s get it set up.&lt;/p&gt;
&lt;h2 id=&quot;Installing-Husky&quot; style=&quot;position:relative;&quot;&gt;Installing Husky&lt;a href=&quot;#Installing-Husky&quot; aria-label=&quot;Installing Husky permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To install Husky, run:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; husky --save-dev&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Configuring-Husky&quot; style=&quot;position:relative;&quot;&gt;Configuring Husky&lt;a href=&quot;#Configuring-Husky&quot; aria-label=&quot;Configuring Husky permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To configure Husky, in the root of our project&apos;s &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;, add the following &lt;code class=&quot;language-text&quot;&gt;husky&lt;/code&gt; key:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;package.json&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;husky&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;hooks&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;pre-commit&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;       &lt;span class=&quot;token comment&quot;&gt;// Command goes here&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;pre-push&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;         &lt;span class=&quot;token comment&quot;&gt;// Command goes here&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;...&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When we execute the &lt;code class=&quot;language-text&quot;&gt;git commit&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;git push&lt;/code&gt; command, the respective hook will run the script we supply in our &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Example-workflow&quot; style=&quot;position:relative;&quot;&gt;Example workflow&lt;a href=&quot;#Example-workflow&quot; aria-label=&quot;Example workflow permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Following along from the previous articles, if we&apos;ve configured ESLint and Prettier, I suggest to utilize two scripts: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;prettier-format&lt;/code&gt;: Format as much code as possible.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;lint&lt;/code&gt;: Ensure that the coding conventions are being adhered to. Throw an error if important conventions are broken.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;filename&quot;&gt;package.json&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;prettier-format&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;prettier --config .prettierrc &apos;src/**/*.ts&apos; --write&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;lint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;eslint . --ext .ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;    ...
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;husky&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;hooks&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;pre-commit&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;npm run prettier-format &amp;amp;&amp;amp; npm run lint&quot;&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Include these scripts in the &lt;code class=&quot;language-text&quot;&gt;scripts&lt;/code&gt; object in your &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;. Then, &lt;em&gt;at the very least&lt;/em&gt;, run &lt;code class=&quot;language-text&quot;&gt;prettier-format&lt;/code&gt; and then &lt;code class=&quot;language-text&quot;&gt;lint&lt;/code&gt; as a &lt;code class=&quot;language-text&quot;&gt;pre-commit&lt;/code&gt; hook.&lt;/p&gt;
&lt;p&gt;This will ensure that you cannot complete a &lt;code class=&quot;language-text&quot;&gt;commit&lt;/code&gt; without formatted code that passes the conventions.&lt;/p&gt;
&lt;h3 id=&quot;No-loops-example&quot; style=&quot;position:relative;&quot;&gt;No-loops example&lt;a href=&quot;#No-loops-example&quot; aria-label=&quot;No loops example permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I like to use the &lt;a href=&quot;https://github.com/buildo/eslint-plugin-no-loops&quot;&gt;no-loops&lt;/a&gt; package as an example. This convention doesn&apos;t allow developers to use &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; loops, and instead suggests that we use Array utility functions like &lt;code class=&quot;language-text&quot;&gt;forEach&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt;, and the like.&lt;/p&gt;
&lt;p&gt;Adding the plugin and its rule to the &lt;code class=&quot;language-text&quot;&gt;.eslintrc&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;.eslintrc&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;parser&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint/parser&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;plugins&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;no-loops&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;prettier&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;extends&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;eslint:recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;plugin:@typescript-eslint/eslint-recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;plugin:@typescript-eslint/recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;prettier&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;rules&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;no-loops/no-loops&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 2 means throw an ERROR &lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;no-console&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;prettier/prettier&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then placing a &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; loop in the source code...&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;src/index.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Hello world!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And attempting to commit, it should exit with a non-zero exit code, which as we know, means an error occurred.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;simple-typescript-starter git:&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prettier&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ✗ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit -m &lt;span class=&quot;token string&quot;&gt;&quot;Test commit&quot;&lt;/span&gt;
husky &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; pre-commit &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node v10.10.0&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; typescript-starter@1.0.0 prettier-format simple-typescript-starter
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; prettier --config .prettierrc &lt;span class=&quot;token string&quot;&gt;&apos;src/**/*.ts&apos;&lt;/span&gt; --write

src/index.ts 191ms

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; typescript-starter@1.0.0 lint /simple-typescript-starter
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; eslint &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; --ext .ts


/simple-typescript-starter/src/index.ts
  &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;:1  warning  Unexpected console statement  no-console
  &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;:1  error    loops are not allowed         no-loops/no-loops
  &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;:3  warning  Unexpected console statement  no-console

✖ &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; problems &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; error, &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; warnings&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And there it is!&lt;/p&gt;
&lt;h2 id=&quot;Other-considerations&quot; style=&quot;position:relative;&quot;&gt;Other considerations&lt;a href=&quot;#Other-considerations&quot; aria-label=&quot;Other considerations permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you notice that linting is taking a long time, check out this package, &lt;a href=&quot;https://github.com/okonet/lint-staged&quot;&gt;lint-staged&lt;/a&gt;. It runs the linter, but only against files that are staged (files that you&apos;re ready to push). This was suggested to me by &lt;a href=&quot;https://twitter.com/glambertmtl&quot;&gt;@glambertmtl&lt;/a&gt;. Thank you!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to use ESLint with TypeScript]]></title><description><![CDATA[Intro Formatting is one of several concerns in the efforts to write clean code. There's a lot of other stuff we should be concerned about as…]]></description><link>https://khalilstemmler.com/blogs/typescript/eslint-for-typescript/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/typescript/eslint-for-typescript/</guid><pubDate>Wed, 26 Feb 2020 15:04:10 GMT</pubDate><content:encoded>&lt;h2 id=&quot;Intro&quot; style=&quot;position:relative;&quot;&gt;Intro&lt;a href=&quot;#Intro&quot; aria-label=&quot;Intro permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Formatting&lt;/strong&gt; is one of several concerns in the efforts to write &lt;em&gt;clean code&lt;/em&gt;. There&apos;s a lot of other stuff we should be concerned about as well, but formatting is one of those things that we can set up right off the bat and establish a standard for our project.&lt;/p&gt;
&lt;h3 id=&quot;ESLint-and-TSLint&quot; style=&quot;position:relative;&quot;&gt;ESLint and TSLint&lt;a href=&quot;#ESLint-and-TSLint&quot; aria-label=&quot;ESLint and TSLint permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://eslint.org/&quot;&gt;ESLint&lt;/a&gt; is a JavaScript &lt;em&gt;linter&lt;/em&gt; that enables you to enforce a set of style, formatting, and coding standards for your codebase. It looks at your code, and tells you when you&apos;re not following the standard that you set in place.&lt;/p&gt;
&lt;p&gt;You may have also heard of &lt;a href=&quot;https://palantir.github.io/tslint/&quot;&gt;TSLint&lt;/a&gt;, the TypeScript equivalent. In 2019, the team behind TSLint &lt;a href=&quot;https://medium.com/palantir/tslint-in-2019-1a144c2317a9a&quot;&gt;decided that they would no longer support it&lt;/a&gt;. The reason, primarily, is because &lt;em&gt;ESLint exists&lt;/em&gt;, and there was a lot of duplicate code between projects with the same intended purpose.&lt;/p&gt;
&lt;p&gt;That being said, there are some really awesome TSLint packages out there that, if you would like to use, you can- but just understand that they&apos;re not being supported anymore.&lt;/p&gt;
&lt;p&gt;So onwards into 2020 and beyond, we&apos;re going to continue to look to ESLint for all of our TypeScript (and JavaScript) linting needs!&lt;/p&gt;
&lt;!-- ### Prettier

[Prettier](https://prettier.io/) is another tool that goes a step further and actually _formats your code_ on the spot. Combined with ESLint, it can be pretty powerful. If Prettier knows how to fix your code, it will do that _on save_ (if you configure it to do so). --&gt;
&lt;h2 id=&quot;Prerequisites&quot; style=&quot;position:relative;&quot;&gt;Prerequisites&lt;a href=&quot;#Prerequisites&quot; aria-label=&quot;Prerequisites permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&apos;s what you need to have in order to follow along:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A code editor installed (psst- VS Code is ideal)&lt;/li&gt;
&lt;li&gt;An existing codebase (if you need to get setup, you can follow &quot;&lt;a href=&quot;/blogs/typescript/node-starter-project/&quot;&gt;How to Setup a TypeScript + Node.js Project&lt;/a&gt; first and then come back to this article)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Installation-and-setup&quot; style=&quot;position:relative;&quot;&gt;Installation and setup&lt;a href=&quot;#Installation-and-setup&quot; aria-label=&quot;Installation and setup permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Run the following commands to setup ESLint in your TypeScript project.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Create an &lt;code class=&quot;language-text&quot;&gt;.eslintrc&lt;/code&gt; file.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; .eslintrc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In it, use the following starter config.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;parser&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint/parser&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;plugins&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;extends&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;eslint:recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;plugin:@typescript-eslint/eslint-recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;plugin:@typescript-eslint/recommended&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Ignoring-files-we-dont-want-to-lint&quot; style=&quot;position:relative;&quot;&gt;Ignoring files we don&apos;t want to lint&lt;a href=&quot;#Ignoring-files-we-dont-want-to-lint&quot; aria-label=&quot;Ignoring files we dont want to lint permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Create an &lt;code class=&quot;language-text&quot;&gt;.eslintignore&lt;/code&gt; in order to prevent ESLint from linting stuff we don&apos;t want it to.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; .eslintignore&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then add the things we want to ignore. In the following code sample, we&apos;re ignoring the &lt;code class=&quot;language-text&quot;&gt;dist/&lt;/code&gt; folder that contains the compiled TypeScript code. If you&apos;re compiling your TypeScript code to a different folder, make sure to use that instead of &lt;code class=&quot;language-text&quot;&gt;dist&lt;/code&gt;. You should be able to find this in your &lt;code class=&quot;language-text&quot;&gt;.tsconfig&lt;/code&gt; (see the &lt;a href=&quot;/blogs/typescript/node-starter-project/&quot;&gt;previous guide&lt;/a&gt;).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;node_modules
dist&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Adding-a-lint-script&quot; style=&quot;position:relative;&quot;&gt;Adding a lint script&lt;a href=&quot;#Adding-a-lint-script&quot; aria-label=&quot;Adding a lint script permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In your project &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;, lets add a &lt;code class=&quot;language-text&quot;&gt;lint&lt;/code&gt; script in order to lint all TypeScript code.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ...
    &lt;span class=&quot;token property&quot;&gt;&quot;lint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;eslint . --ext .ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ready to try it out? Let&apos;s run the following command.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run lint&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For &lt;em&gt;me&lt;/em&gt;, since I&apos;m continuing with the &lt;a href=&quot;/blogs/typescript/node-starter-project/&quot;&gt;previous tutorial&lt;/a&gt;, and since my &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; folder only has a single &lt;code class=&quot;language-text&quot;&gt;index.ts&lt;/code&gt; in it that prints out some text with &lt;code class=&quot;language-text&quot;&gt;console.log()&lt;/code&gt;, I don&apos;t see anything after I run the command.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;src/index.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Hello world!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What if we wanted to &lt;em&gt;disallow&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;console.log&lt;/code&gt; statements in our code? &lt;/p&gt;
&lt;h2 id=&quot;Rules&quot; style=&quot;position:relative;&quot;&gt;Rules&lt;a href=&quot;#Rules&quot; aria-label=&quot;Rules permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are three modes for a rule in eslint: &lt;code class=&quot;language-text&quot;&gt;off&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;warn&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;error&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;off&quot; means 0 (turns the rule off completely)&lt;/li&gt;
&lt;li&gt;&quot;warn&quot; means 1 (turns the rule on but won&apos;t make the linter fail)&lt;/li&gt;
&lt;li&gt;&quot;error&quot; means 2 (turns the rule on and will make the linter fail)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Adding-a-rule&quot; style=&quot;position:relative;&quot;&gt;Adding a rule&lt;a href=&quot;#Adding-a-rule&quot; aria-label=&quot;Adding a rule permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In &lt;code class=&quot;language-text&quot;&gt;.eslintrc&lt;/code&gt;, add a new attribute to the json object called &quot;rules&quot;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;parser&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint/parser&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;plugins&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;extends&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;eslint:recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;plugin:@typescript-eslint/eslint-recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;plugin:@typescript-eslint/recommended&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;rules&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Rules get added as keys of this &lt;code class=&quot;language-text&quot;&gt;rules&lt;/code&gt; attribute, and you can normally find the &lt;code class=&quot;language-text&quot;&gt;eslint&lt;/code&gt; base rules &lt;a href=&quot;https://eslint.org/docs/rules/&quot;&gt;here on their website via the Rules docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We want to add the &lt;a href=&quot;https://eslint.org/docs/rules/no-console&quot;&gt;no-console&lt;/a&gt; rule, so here is an example of how we can make the linter fail (throw a mean error code) if it encounters a &lt;code class=&quot;language-text&quot;&gt;console.log&lt;/code&gt; statement with the &lt;code class=&quot;language-text&quot;&gt;no-console&lt;/code&gt; rule set to &lt;code class=&quot;language-text&quot;&gt;error&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We update the &lt;code class=&quot;language-text&quot;&gt;.eslintrc&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;parser&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint/parser&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;plugins&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;extends&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;eslint:recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;plugin:@typescript-eslint/eslint-recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;plugin:@typescript-eslint/recommended&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;rules&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;no-console&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Remember, this means error!&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then run the linter again.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run lint&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we should get an angry linting result.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;/simple-typescript-starter/src/index.ts

  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;:1  error  Unexpected console statement  no-console
    ✖ &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; problem &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; error, &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; warnings&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And if we wanted, we could turn the rule off by setting it to &lt;code class=&quot;language-text&quot;&gt;0 - off&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;parser&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint/parser&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;plugins&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;extends&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;eslint:recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;plugin:@typescript-eslint/eslint-recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;plugin:@typescript-eslint/recommended&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;rules&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;/span&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;no-console&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; 
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Run the linter.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run lint&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;...and silence.&lt;/p&gt;
&lt;h3 id=&quot;Using-rules-in-a-real-life-project&quot; style=&quot;position:relative;&quot;&gt;Using rules in a real-life project&lt;a href=&quot;#Using-rules-in-a-real-life-project&quot; aria-label=&quot;Using rules in a real life project permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There&apos;s a reason that all three of these modes exist. When you set the linter to &lt;code class=&quot;language-text&quot;&gt;off&lt;/code&gt; for a rule, it&apos;s because you and your team probably don&apos;t care about &lt;em&gt;that rule&lt;/em&gt; in a particular &lt;strong&gt;base configuration&lt;/strong&gt; you&apos;re using (we&apos;re currently using the ESLint recommended config but you can also go and use &lt;a href=&quot;https://github.com/Shopify/eslint-plugin-shopify&quot;&gt;Shopify&apos;s&lt;/a&gt;, &lt;a href=&quot;https://www.npmjs.com/package/eslint-config-fbjs&quot;&gt;Facebook&apos;s&lt;/a&gt; or several other companies&apos; configs as starting points instead).&lt;/p&gt;
&lt;p&gt;When you set the rule to &lt;code class=&quot;language-text&quot;&gt;error - 2&lt;/code&gt;, it means that you don&apos;t want the code that breaks your coding conventions to even make it into the repo at all. I think this is a great act of professionalism and empathy towards the codebase, your fellow teammates, and future maintainers. A popular approach to &lt;strong&gt;actually enforce&lt;/strong&gt; code conventions with this tool is to set up your project with a tool like &lt;a href=&quot;https://github.com/typicode/husky&quot;&gt;Husky&lt;/a&gt; so that when a teammate tries to &lt;strong&gt;commit&lt;/strong&gt; code or &lt;strong&gt;push&lt;/strong&gt; code, you can tell your linter to check the code first before the operation executes. It&apos;s a great habit, though sometimes, if the rules are overly restrictive, it can slow down and annoy your teammates.&lt;/p&gt;
&lt;p&gt;To remedy overly restrictive rules, the &lt;code class=&quot;language-text&quot;&gt;warn - 1&lt;/code&gt; setting means that yes, you want you and your team to adhere to that rule, but you don&apos;t want it to prevent you from moving forward.&lt;/p&gt;
&lt;h2 id=&quot;Adding-a-plugin-features&quot; style=&quot;position:relative;&quot;&gt;Adding a plugin (features)&lt;a href=&quot;#Adding-a-plugin-features&quot; aria-label=&quot;Adding a plugin features permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;ESLint also allows you to add one-off features to your config. These are known as &lt;em&gt;plugins&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Here&apos;s a fun one. It&apos;s called &lt;a href=&quot;https://github.com/buildo/eslint-plugin-no-loops&quot;&gt;no-loops&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;Check out this list of other &lt;a href=&quot;https://github.com/dustinspecker/awesome-eslint&quot;&gt;awesome-eslint&lt;/a&gt; plugins and configs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;no-loops&lt;/strong&gt; is a plugin that will enable you to enforce a convention specifying that &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;while&lt;/code&gt; loops are illegal and that you should use functions like &lt;code class=&quot;language-text&quot;&gt;map&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;forEach&lt;/code&gt; instead.&lt;/p&gt;
&lt;p&gt;Install it like this.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save-dev eslint-plugin-no-loops&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then update your &lt;code class=&quot;language-text&quot;&gt;.eslintrc&lt;/code&gt; with &lt;code class=&quot;language-text&quot;&gt;no-loops&lt;/code&gt; in the &quot;plugins&quot; array, and add the rule to the &quot;rules&quot; attribute like so.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;parser&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint/parser&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;plugins&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;no-loops&quot;&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;extends&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;eslint:recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;plugin:@typescript-eslint/eslint-recommended&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;plugin:@typescript-eslint/recommended&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;rules&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;no-console&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;no-loops/no-loops&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now if we update our code to include a &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; loop...&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;src/index.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Hello world!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And run the lint command again...&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run lint&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We&apos;ll see the errors that restricts loops appear.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;/simple-typescript-starter/src/index.ts
  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;:1   warning  Unexpected console statement                   no-console
  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;:1   error    &lt;span class=&quot;token string&quot;&gt;&apos;console&apos;&lt;/span&gt; is not defined                       no-undef
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;:1   error    loops are not allowed                          no-loops/no-loops&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;:3   warning  Unexpected console statement                   no-console
  &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;:3   error    &lt;span class=&quot;token string&quot;&gt;&apos;console&apos;&lt;/span&gt; is not defined                       no-undef
  &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;:17  error    Missing semicolon                              babel/semi
  &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;:17  error    Missing semicolon                              semi
  &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;:2   error    Newline required at end of &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; but not found  eol-last

✖ &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt; problems &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; errors, &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; warnings&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; errors and &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; warnings potentially fixable with the &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;--fix&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt; option.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Extending-a-different-base-config&quot; style=&quot;position:relative;&quot;&gt;Extending a different base config&lt;a href=&quot;#Extending-a-different-base-config&quot; aria-label=&quot;Extending a different base config permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&apos;s say that you wanted to start with a different base config- &lt;a href=&quot;https://github.com/Shopify/eslint-plugin-shopify&quot;&gt;Shopify&apos;s&lt;/a&gt;, for example.&lt;/p&gt;
&lt;p&gt;Here&apos;s how to do that. &lt;/p&gt;
&lt;p&gt;Looking at the &lt;a href=&quot;https://github.com/Shopify/eslint-plugin-shopify&quot;&gt;readme&lt;/a&gt;, we need to install it by running:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; eslint-plugin-shopify --save-dev&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Update our &lt;code class=&quot;language-text&quot;&gt;.eslintrc&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;parser&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint/parser&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;plugins&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;@typescript-eslint&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;extends&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;plugin:shopify/esnext&quot;&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;rules&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;no-console&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;You can add several base configs to your project by including them in the array, though you may end up seeeing the same linting rules twice or more.&lt;/p&gt;
&lt;p&gt;Now when we run the lint command again with &lt;code class=&quot;language-text&quot;&gt;npm run lint&lt;/code&gt;, we can see a few errors reported based on the base Shopify config and our &lt;code class=&quot;language-text&quot;&gt;no-console&lt;/code&gt; rule.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;/simple-typescript-starter/src/index.ts
  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;:1   warning  Unexpected console statement  no-console
  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;:1   error    &lt;span class=&quot;token string&quot;&gt;&apos;console&apos;&lt;/span&gt; is not defined      no-undef
  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;:28  error    Missing semicolon             babel/semi
  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;:28  error    Missing semicolon             semi

✖ &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; problems &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; errors, &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; warning&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; errors and &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; warnings potentially fixable with the &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;--fix&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt; option.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Fixing-linted-code-with-ESLint&quot; style=&quot;position:relative;&quot;&gt;Fixing linted code with ESLint&lt;a href=&quot;#Fixing-linted-code-with-ESLint&quot; aria-label=&quot;Fixing linted code with ESLint permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You might have noticed that at the end of the error message, it says &quot;2 errors and 0 warnings potentially fixable with the &lt;code class=&quot;language-text&quot;&gt;--fix&lt;/code&gt; option.&quot;&lt;/p&gt;
&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; run ESLint and tell it to fix things that it&apos;s able to fix at the same time.&lt;/p&gt;
&lt;p&gt;Using the &lt;code class=&quot;language-text&quot;&gt;--fix&lt;/code&gt; option, let&apos;s add a new script to our &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt; called &lt;code class=&quot;language-text&quot;&gt;lint-and-fix&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ...
    &lt;span class=&quot;token property&quot;&gt;&quot;lint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;eslint . --ext .ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;lint-and-fix&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;eslint . --ext .ts --fix&quot;&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Running this command against our code, I expect that it will put a semicolon on the &lt;code class=&quot;language-text&quot;&gt;console.log&lt;/code&gt; statement that we had.&lt;/p&gt;
&lt;p&gt;Let&apos;s run it.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run lint-and-fix&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The result is that &lt;em&gt;less&lt;/em&gt; errors are reported. We don&apos;t see the error about semi-colons anymore.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;/simple-typescript-starter/src/index.ts
  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;:1  warning  Unexpected console statement  no-console
  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;:1  error    &lt;span class=&quot;token string&quot;&gt;&apos;console&apos;&lt;/span&gt; is not defined      no-undef&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Because sure enough, the linter added the semi-colon.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;src/index.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Hello world!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&apos;s really awesome. But what if we don&apos;t want to run the linter all the time to fix our code? What if there was a way that we could, while coding, have it &lt;em&gt;automatically&lt;/em&gt; format things based on our conventions?&lt;/p&gt;
&lt;p&gt;We can! With &lt;a href=&quot;https://prettier.io/&quot;&gt;Prettier&lt;/a&gt;. Read the next article, &quot;&lt;a href=&quot;/blogs/tooling/prettier/&quot;&gt;How to use Prettier with ESLint and TypeScript in VSCode&lt;/a&gt;&quot;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Deploying Serverless GraphQL APIs with TypeScript on Netlify]]></title><description><![CDATA[Deploying a Serverless GraphQL API with TypeScript is essentially the same as deploying one with JavaScript. The only difference is in the…]]></description><link>https://khalilstemmler.com/blogs/graphql/serverless-graphql-typescript/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/graphql/serverless-graphql-typescript/</guid><pubDate>Sun, 23 Feb 2020 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Deploying a Serverless GraphQL API with TypeScript is essentially the same as deploying one with JavaScript.&lt;/p&gt;
&lt;p&gt;The only difference is in the build steps.&lt;/p&gt;
&lt;p&gt;For example, using vanilla JavaScript on Netlify, the build step in our &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt; is usually to &lt;strong&gt;copy all of the vanilla JavaScript code in our &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; folder&lt;/strong&gt; over to the &lt;code class=&quot;language-text&quot;&gt;functions&lt;/code&gt; folder.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;package.json&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;start&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nodemon&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;bundle&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cpx src/**/* functions/bundle&quot;&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While building with TypeScript is effectively the same, just through different means. In a TypeScript environment, we configure a &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt; and run &lt;code class=&quot;language-text&quot;&gt;tsc&lt;/code&gt; as the build step.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;package.json&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;allowJs&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;module&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;commonjs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;moduleResolution&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;pretty&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;sourceMap&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;target&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;es2017&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;outDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./functions/bundle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;lib&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;es6&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;resolveJsonModule&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;types&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;typeRoots&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./node_modules/@types&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./src/@types&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;experimentalDecorators&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;emitDecoratorMetadata&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;esModuleInterop&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;include&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;src/*.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;src/**/*.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;src/**/*.js&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;exclude&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;node_modules&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;src/**/*.spec.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;src/**/*.spec.js&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;filename&quot;&gt;package.json&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;start&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nodemon&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;bundle&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tsc&quot;&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Either way, the result is the same since Netlify needs all of the source code used in the &lt;code class=&quot;language-text&quot;&gt;functions&lt;/code&gt; direction to be bundled before it&apos;s deployed.&lt;/p&gt;
&lt;h2 id=&quot;Resources&quot; style=&quot;position:relative;&quot;&gt;Resources&lt;a href=&quot;#Resources&quot; aria-label=&quot;Resources permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Check out these starters for deploying your own Serverless GraphQL APIs on Netlify with TypeScript or vanilla JavaScript.&lt;/p&gt;
&lt;h3 id=&quot;Starters&quot; style=&quot;position:relative;&quot;&gt;Starters&lt;a href=&quot;#Starters&quot; aria-label=&quot;Starters permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/stemmlerjs/serverless-graphql-netlify-starter&quot;&gt;Serverless GraphQL on Netlify API Starter Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/stemmlerjs/serverless-graphql-netlify-starter&quot;&gt;Serverless GraphQL on Netlify API using TypeScript Starter Project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Tutorial&quot; style=&quot;position:relative;&quot;&gt;Tutorial&lt;a href=&quot;#Tutorial&quot; aria-label=&quot;Tutorial permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you&apos;re interested in how the starters were built, read &quot;&lt;a href=&quot;/articles/tutorials/deploying-a-serverless-graphql-api-on-netlify/&quot;&gt;How to Deploy a Serverless GraphQL API on Netlify [Starters]&lt;/a&gt;&quot;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to Deploy a Serverless GraphQL API on Netlify [Starters]]]></title><description><![CDATA[You know, I'm very proud to be a developer in 2020. The access we have to tools and services is impressive. The barrier to entry towards…]]></description><link>https://khalilstemmler.com/articles/tutorials/deploying-a-serverless-graphql-api-on-netlify/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/tutorials/deploying-a-serverless-graphql-api-on-netlify/</guid><pubDate>Sun, 23 Feb 2020 04:05:26 GMT</pubDate><content:encoded>&lt;p&gt;You know, I&apos;m very proud to be a developer in 2020. The access we have to tools and services is impressive. The barrier to entry towards crafting side-projects, startups, businesses, etc.- it&apos;s almost non-existent.&lt;/p&gt;
&lt;p&gt;With tools like &lt;a href=&quot;https://www.netlify.com/&quot;&gt;Netlify&lt;/a&gt;, we can deploy a &lt;em&gt;serverless&lt;/em&gt; Apollo GraphQL server for free in seconds. Un. Real.&lt;/p&gt;
&lt;p&gt;While I like being able to do things quickly, I&apos;m also one who believes that &quot;if we do it, we know it&quot;. So I&apos;m going to give you a few useful resources on how to deploy serverless GraphQL APIs and then walk you through the process so that you can better appreciate what&apos;s going on. &lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;Huge shoutout to the great &lt;a href=&quot;https://twitter.com/trevorblades&quot;&gt;Trevor Blades&lt;/a&gt; who cut 80% of the time it would have taken me to figure this stuff out on my own. Most of this is based off of his &lt;a href=&quot;https://github.com/trevorblades/countries&quot;&gt;Countries GraphQL API&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Prerequisites&quot; style=&quot;position:relative;&quot;&gt;Prerequisites&lt;a href=&quot;#Prerequisites&quot; aria-label=&quot;Prerequisites permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;You should have Node and npm installed&lt;/li&gt;
&lt;li&gt;You should understand the concept of serverless functions&lt;/li&gt;
&lt;li&gt;You have a code editor installed (preferably VS Code, it&apos;s the champ, don&apos;t @ me)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Goals&quot; style=&quot;position:relative;&quot;&gt;Goals&lt;a href=&quot;#Goals&quot; aria-label=&quot;Goals permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;By the &lt;strong&gt;start&lt;/strong&gt; of this article (like- right now), you should be aware of two resources to deploy GraphQL APIs on Netlify. Check them out below.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/stemmlerjs/serverless-graphql-netlify-starter&quot;&gt;Serverless GraphQL on Netlify API Starter Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/stemmlerjs/serverless-typescript-graphql-netlify-starter&quot;&gt;Serverless GraphQL on Netlify API using TypeScript Starter Project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you just need to get something up and running, you can go to either of those projects, click &quot;Deploy to Netlify&quot;, and you&apos;re good to go. You can even stop reading right here.&lt;/p&gt;
&lt;p&gt;The second goal for the &lt;strong&gt;rest&lt;/strong&gt; of this article is to explain &lt;em&gt;how&lt;/em&gt; these starters work, what they can do, and how you can use them for your next serverless project.&lt;/p&gt;
&lt;p&gt;We will go through the process of creating a GraphQL API using Netlify from scratch with vanilla JavaScript (though the process is similar with TypeScript).&lt;/p&gt;
&lt;h2 id=&quot;Initial-setup&quot; style=&quot;position:relative;&quot;&gt;Initial setup&lt;a href=&quot;#Initial-setup&quot; aria-label=&quot;Initial setup permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First we need to create a folder.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; serverless-starter
&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; serverless-starter&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Setup-Nodejs-packagejson&quot; style=&quot;position:relative;&quot;&gt;Setup Node.js package.json&lt;a href=&quot;#Setup-Nodejs-packagejson&quot; aria-label=&quot;Setup Nodejs packagejson permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Next, we&apos;ll create a &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt; and say &quot;yes&quot; to everything.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; init -y&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Install-dependencies&quot; style=&quot;position:relative;&quot;&gt;Install dependencies&lt;a href=&quot;#Install-dependencies&quot; aria-label=&quot;Install dependencies permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We don&apos;t need a whole lot to get things going. In your console, paste the following command to install the dependencies.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save apollo-server apollo-server-lambda
&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save-dev cpx nodemon&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;apollo-server&lt;/code&gt;: When we&apos;re developing locally, we&apos;re going to want to run our code against a local GraphQL endpoint. Let&apos;s install this so that we can craft an excellent local development experience.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;apollo-server-lambda&lt;/code&gt;: This is a version of Apollo Server optimized to work on serverless lambda functions. It&apos;s what we use to deploy to production.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;cpx&lt;/code&gt;: In Netlify, we need to bundle all of our source code in the &lt;code class=&quot;language-text&quot;&gt;functions/&lt;/code&gt; folder, so we need a way to copy the code from our &lt;code class=&quot;language-text&quot;&gt;src/&lt;/code&gt; folder in a cross-platform-friendly way to the &lt;code class=&quot;language-text&quot;&gt;functions/&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;nodemon&lt;/code&gt;: We all like cold-reloading. Install this so that we can get live updates when we change any files.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Creating-our-server-implementations&quot; style=&quot;position:relative;&quot;&gt;Creating our server implementations&lt;a href=&quot;#Creating-our-server-implementations&quot; aria-label=&quot;Creating our server implementations permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&apos;s create our server implementations at &lt;code class=&quot;language-text&quot;&gt;src/server.js&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; src/server.js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In &lt;code class=&quot;language-text&quot;&gt;server.js&lt;/code&gt;, we&apos;re going to import both the &lt;code class=&quot;language-text&quot;&gt;ApolloServer&lt;/code&gt; from &lt;code class=&quot;language-text&quot;&gt;apollo-server&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;apollo-server-lambda&lt;/code&gt;, but we&apos;re going to call the one imported from the lambda project, &lt;code class=&quot;language-text&quot;&gt;ApolloServerLambda&lt;/code&gt; instead.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;server.js&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ApolloServer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;apollo-server&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ApolloServer
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ApolloServerLambda &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;apollo-server-lambda&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ApolloServer
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; gql &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;apollo-server-lambda&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now let&apos;s add a simple type definition and resolvers object.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;server.js&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; typeDefs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; gql&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
  type Query {
    hello: String
  }
&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; resolvers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Query&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hi! Love from @khalilstemmler 🤠.&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The last thing in this file- let&apos;s create two &lt;strong&gt;factory functions&lt;/strong&gt;: one for the lambda server, and one for the regular server. We&apos;ll also export these from the module as an object.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;server.js&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createLambdaServer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ApolloServerLambda&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    typeDefs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    resolvers&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    introspection&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    playground&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createLocalServer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ApolloServer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    typeDefs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    resolvers&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    introspection&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    playground&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createLambdaServer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; createLocalServer &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Sweet, now let&apos;s get our local server going.&lt;/p&gt;
&lt;h3 id=&quot;Configuring-our-local-server&quot; style=&quot;position:relative;&quot;&gt;Configuring our local server&lt;a href=&quot;#Configuring-our-local-server&quot; aria-label=&quot;Configuring our local server permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Create &lt;code class=&quot;language-text&quot;&gt;src/index.js&lt;/code&gt;, the entry point to our local development efforts.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; src/index.js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then import &lt;code class=&quot;language-text&quot;&gt;createLocalServer&lt;/code&gt; from &lt;code class=&quot;language-text&quot;&gt;./server&lt;/code&gt;, create a server instance, and fire it up.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;src/index.js&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createLocalServer &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./server&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; server &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createLocalServer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;🚀 Server ready at &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;url&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nice! That&apos;s how we get a &lt;strong&gt;local&lt;/strong&gt; GraphQL server up and running. &lt;/p&gt;
&lt;h3 id=&quot;Starting-up-the-local-server-with-Nodemon&quot; style=&quot;position:relative;&quot;&gt;Starting up the local server with Nodemon&lt;a href=&quot;#Starting-up-the-local-server-with-Nodemon&quot; aria-label=&quot;Starting up the local server with Nodemon permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Because we like cold-reloading, let&apos;s create a &lt;code class=&quot;language-text&quot;&gt;nodemon.json&lt;/code&gt; file in the root of the project and add configure it to listen to changes to anything in &lt;code class=&quot;language-text&quot;&gt;src/&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;functions/&lt;/code&gt; (this is where we will configure our GraphQL server).&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;nodemon.json&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;watch&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;functions&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;ext&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;ignore&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;exec&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node ./src/index.js&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;, we can add a &lt;code class=&quot;language-text&quot;&gt;start&lt;/code&gt; script that simply executes nodemon like so.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;package.json&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;start&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nodemon&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To start the project, run this command.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run start&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then go to &lt;code class=&quot;language-text&quot;&gt;http://localhost:4000/&lt;/code&gt; and check out the local server.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tutorials/serverless-graphql/1-deployed.png&quot; alt=&quot;Serverless GraphQL Local Server&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Configuring-our-lambda-server&quot; style=&quot;position:relative;&quot;&gt;Configuring our lambda server&lt;a href=&quot;#Configuring-our-lambda-server&quot; aria-label=&quot;Configuring our lambda server permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now that we&apos;ve got the local server running, it&apos;s time to hook up the one that will run on Netlify.&lt;/p&gt;
&lt;h3 id=&quot;Create-the-functions-directory&quot; style=&quot;position:relative;&quot;&gt;Create the functions directory&lt;a href=&quot;#Create-the-functions-directory&quot; aria-label=&quot;Create the functions directory permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;At the root of the project, create a directory called &lt;code class=&quot;language-text&quot;&gt;functions/&lt;/code&gt;-  this is where we&apos;ll tell Netlify to look for our functions.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; functions&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Create-the-serverless-graphql-endpoint&quot; style=&quot;position:relative;&quot;&gt;Create the serverless graphql endpoint&lt;a href=&quot;#Create-the-serverless-graphql-endpoint&quot; aria-label=&quot;Create the serverless graphql endpoint permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In &lt;code class=&quot;language-text&quot;&gt;functions&lt;/code&gt;, create a file called &lt;code class=&quot;language-text&quot;&gt;graphql.js&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; functions/graphql.js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Whatever we put in the &lt;code class=&quot;language-text&quot;&gt;functions&lt;/code&gt; folder, Netlify will make it publicly visible as if it were in a directory.&lt;/p&gt;
&lt;p&gt;When we deploy this, we will be able to reach this file directly by going to &lt;a href=&quot;https://OUR_SITE_NAME/.netlify/functions/graphql&quot;&gt;https://OUR_SITE_NAME/.netlify/functions/graphql&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let&apos;s get access to our &lt;code class=&quot;language-text&quot;&gt;createLambdaServer&lt;/code&gt; factory function, call it, and then expose a &lt;code class=&quot;language-text&quot;&gt;handler&lt;/code&gt; using &lt;code class=&quot;language-text&quot;&gt;server.createHandler&lt;/code&gt;, passing in the most permissive CORS configuration.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;functions/graphql.js&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createLambdaServer &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;../src/server&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; server &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createLambdaServer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handler &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  cors&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    origin&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;*&apos;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This looks good, but there&apos;s a problem here. &lt;strong&gt;Netlify can&apos;t reach outside of the &lt;code class=&quot;language-text&quot;&gt;functions&lt;/code&gt; folder and into &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If we were to deploy this, Netlify would yell at us and tell us that it can&apos;t find &lt;code class=&quot;language-text&quot;&gt;createLambdaServer&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The solution is to bundle the code in &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; and copy it over to the &lt;code class=&quot;language-text&quot;&gt;functions&lt;/code&gt; folder.&lt;/p&gt;
&lt;h3 id=&quot;Bundling-our-source-code&quot; style=&quot;position:relative;&quot;&gt;Bundling our source code&lt;a href=&quot;#Bundling-our-source-code&quot; aria-label=&quot;Bundling our source code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In our &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;, let&apos;s add the &lt;code class=&quot;language-text&quot;&gt;bundle&lt;/code&gt; script.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;package.json&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;bundle&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cpx src/**/* functions/bundle&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This command takes everything in &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; and copies it to &lt;code class=&quot;language-text&quot;&gt;functions/bundle&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&apos;s give it a run.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run bundle&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You should see a new folder appear in the &lt;code class=&quot;language-text&quot;&gt;functions&lt;/code&gt; folder with the source code from &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Go into &lt;code class=&quot;language-text&quot;&gt;functions/graphql.js&lt;/code&gt; and update the reference to the &lt;code class=&quot;language-text&quot;&gt;createLambdaServer&lt;/code&gt; function.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;functions/graphql.js&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createLambdaServer &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;./bundle/server&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; server &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createLambdaServer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handler &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  cors&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    origin&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;*&apos;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We&apos;re pretty much all set to go! The last thing to do is configure Netlify.&lt;/p&gt;
&lt;h2 id=&quot;Netlify-configuration&quot; style=&quot;position:relative;&quot;&gt;Netlify configuration&lt;a href=&quot;#Netlify-configuration&quot; aria-label=&quot;Netlify configuration permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&apos;s the stuff that&apos;s magic to me. &lt;/p&gt;
&lt;h3 id=&quot;Empty-indexhtml&quot; style=&quot;position:relative;&quot;&gt;Empty index.html&lt;a href=&quot;#Empty-indexhtml&quot; aria-label=&quot;Empty indexhtml permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&apos;m not entirely sure if this is necessary (someone correct me), but an empty &lt;code class=&quot;language-text&quot;&gt;index.html&lt;/code&gt; file should live at the root of the project.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; index.html&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Redirects-file&quot; style=&quot;position:relative;&quot;&gt;Redirects file&lt;a href=&quot;#Redirects-file&quot; aria-label=&quot;Redirects file permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;By default, our endpoint lives at &lt;a href=&quot;https://OUR_SITE_NAME/.netlify/functions/graphql&quot;&gt;https://OUR_SITE_NAME/.netlify/functions/graphql&lt;/a&gt;. We don&apos;t want to have to refer to it like that; we&apos;d prefer to just see to the site like &lt;a href=&quot;https://OUR_SITE_NAME/&quot;&gt;https://OUR_SITE_NAME/&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;To remedy this, create a &lt;code class=&quot;language-text&quot;&gt;_redirects&lt;/code&gt; file at the root of the project.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; _redirects&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then add the following config.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;_redirects&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;/ /.netlify/functions/graphql 200!&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;The exclamation mark signals that we will rewrite &lt;i&gt;everything&lt;/i&gt; at the root URL to /.netlify/functions/graphql. Read more about &lt;a target=&quot;_blank&quot; href=&quot;https://docs.netlify.com/routing/redirects/rewrites-proxies/#shadowing&quot;&gt;Shadowing&lt;/a&gt; from the docs.&lt;/p&gt;
&lt;h3 id=&quot;Netlifytoml-file&quot; style=&quot;position:relative;&quot;&gt;Netlify.toml file&lt;a href=&quot;#Netlifytoml-file&quot; aria-label=&quot;Netlifytoml file permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The last thing we need to do is tell Netlify what the &lt;strong&gt;build&lt;/strong&gt; command is and where our &lt;strong&gt;functions&lt;/strong&gt; live.&lt;/p&gt;
&lt;p&gt;We can do set this up with a &lt;code class=&quot;language-text&quot;&gt;netlify.toml&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;Let&apos;s create one at the root of the project.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; netlify.toml&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And since we need to bundle our code before we deploy, let&apos;s use &lt;code class=&quot;language-text&quot;&gt;npm run bundle&lt;/code&gt; as the build command.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;netlify.toml&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[build]
  command = &amp;quot;npm run bundle&amp;quot;
  functions = &amp;quot;functions&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&apos;s it!&lt;/p&gt;
&lt;h2 id=&quot;Deploying-to-Netlify&quot; style=&quot;position:relative;&quot;&gt;Deploying to Netlify&lt;a href=&quot;#Deploying-to-Netlify&quot; aria-label=&quot;Deploying to Netlify permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Two effortless ways to deploy this are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Click the &quot;Deploy to Netlify&quot; button in either starter. It will clone the repos to your GitHub account and deploy them.&lt;/li&gt;
&lt;li&gt;Manually clone the repos, log in to Netlify, and then select a repository to deploy.&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[Nested GraphQL Resolvers & Separating Concerns]]></title><description><![CDATA[Unfortunately, in GraphQL, you can't nest operations to apply better grouping (namespacing / separation of concerns) to your services. Here…]]></description><link>https://khalilstemmler.com/blogs/graphql/nested-graphql-resolvers/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/graphql/nested-graphql-resolvers/</guid><pubDate>Sat, 22 Feb 2020 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Unfortunately, in GraphQL, you can&apos;t nest operations to apply better grouping (namespacing / separation of concerns) to your services.&lt;/p&gt;
&lt;p&gt;Here&apos;s an example. I was building my own personal data graph with all kinds of cool things on it like my &lt;code class=&quot;language-text&quot;&gt;spotify&lt;/code&gt;, my Google &lt;code class=&quot;language-text&quot;&gt;calendar&lt;/code&gt;, and my &lt;code class=&quot;language-text&quot;&gt;github&lt;/code&gt; activity.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;You can check out my personal data graph at &lt;a href=&quot;https://stemmlerjs-graph.netlify.com/&quot;&gt;stemmlerjs-graph.netlify.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I wanted to design the schema where each service lived at the top-level. That would enable me to separate concerns and place all operations within the services like so:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;schema.graphql&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Spotify&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;getCurrentSong&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Song
  &lt;span class=&quot;token attr-name&quot;&gt;getRecentlyListenedToSongs&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Song&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Calendar&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;getCalendarForMonth&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;month&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Integer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CalendarResult&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GitHub&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;getRecentActivity&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitHubActivityResult&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Query&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;spotify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Spotify
  &lt;span class=&quot;token attr-name&quot;&gt;calendar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Calendar
  &lt;span class=&quot;token attr-name&quot;&gt;github&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; GitHub
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Looking at the structure of the root &lt;code class=&quot;language-text&quot;&gt;Query&lt;/code&gt; type, you&apos;d assume that the resolvers object would assume the same shape of the &lt;code class=&quot;language-text&quot;&gt;Query&lt;/code&gt; type, like so.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;resolvers.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; resolvers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Query&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    spotify&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Will not get invoked.&lt;/span&gt;
      &lt;span class=&quot;token function-variable function&quot;&gt;spotifyGetCurrentSongPlaying&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; currentSongResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; getCurrentSong&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; currentSongResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isRight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; currentSongResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Unfortunately, this won&apos;t work. It&apos;s not that it isn&apos;t valid GraphQL, but it&apos;s just that if we were to do this, &lt;strong&gt;none of our nested resolvers will ever get invoked&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;With &lt;code class=&quot;language-text&quot;&gt;ApolloServer&lt;/code&gt;, if we want to refer to a type nested deeper than one level, that type needs to be defined as its own attribute on the resolvers object like the following.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;resolvers.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; resolvers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Query&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;spotify&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Return nothing&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;

  Spotify&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;spotifyGetCurrentSongPlaying&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; currentSongResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; getCurrentSong&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; currentSongResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isRight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; currentSongResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This works! &lt;/p&gt;
&lt;p&gt;Although on a larger application, we&apos;d like to be able to enforce some sort of namespacing. Some separation of concerns. &lt;/p&gt;
&lt;p&gt;Take the following example of a GraphQL schema with the &lt;code class=&quot;language-text&quot;&gt;users&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;movies&lt;/code&gt; subdomains. Without namespacing, we end up with large schemas that look like the following.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;schema.graphql&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Query&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;Movie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;movieId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;orderBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;_MovieOrdering&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Movie&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;Actor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;actorId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;orderBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;_ActorOrdering&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Actor&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;orderBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;_UserOrdering&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Mutation&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;CreateMovie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;movieId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movie
  &lt;span class=&quot;token attr-name&quot;&gt;UpdateMovie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;movieId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movie
  &lt;span class=&quot;token attr-name&quot;&gt;DeleteMovie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;movieId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movie
  &lt;span class=&quot;token attr-name&quot;&gt;AddMovieActors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _ActorInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _MovieInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _AddMovieActorsPayload
  &lt;span class=&quot;token attr-name&quot;&gt;RemoveMovieActors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _ActorInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _MovieInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _RemoveMovieActorsPayload
  &lt;span class=&quot;token attr-name&quot;&gt;AddMovieRatings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _UserInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _MovieInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _RatingInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _AddMovieRatingsPayload
  &lt;span class=&quot;token attr-name&quot;&gt;CreateActor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;actorId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Actor
  &lt;span class=&quot;token attr-name&quot;&gt;UpdateActor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;actorId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Actor
  &lt;span class=&quot;token attr-name&quot;&gt;DeleteActor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;actorId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Actor
  &lt;span class=&quot;token attr-name&quot;&gt;AddActorMovies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _ActorInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _MovieInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _AddActorMoviesPayload
  &lt;span class=&quot;token attr-name&quot;&gt;RemoveActorMovies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _ActorInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _MovieInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _RemoveActorMoviesPayload
  &lt;span class=&quot;token attr-name&quot;&gt;CreateUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; User
  &lt;span class=&quot;token attr-name&quot;&gt;UpdateUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; User
  &lt;span class=&quot;token attr-name&quot;&gt;DeleteUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; User
  &lt;span class=&quot;token attr-name&quot;&gt;AddUserRating&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _UserInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _MovieInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _RatingInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _AddUserRatingPayload
  &lt;span class=&quot;token attr-name&quot;&gt;RemoveUserRating&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _UserInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _MovieInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _RemoveUserRatingPayload
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;A poorly namespaced GraphQL schema.&lt;/p&gt;
&lt;p&gt;You may be able to see that the grouping and cohesion between related operations are not present here. It&apos;s visually challenging to group all  operations related to &lt;code class=&quot;language-text&quot;&gt;users&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;actors&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;movies&lt;/code&gt; into units. Everything is mixed together.&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design&lt;/a&gt;, each subdomain contains only the operations that are related to that subdomain. Subdomains are well encapsulated.&lt;/p&gt;
&lt;p&gt;For example, looking at these operations, I can deduce that we have two subdomains- a &lt;code class=&quot;language-text&quot;&gt;users&lt;/code&gt; one and a &lt;code class=&quot;language-text&quot;&gt;movies&lt;/code&gt; one (&lt;code class=&quot;language-text&quot;&gt;actor&lt;/code&gt; is a concept that would also belong to &lt;code class=&quot;language-text&quot;&gt;movies&lt;/code&gt;). &lt;/p&gt;
&lt;p&gt;Therefore,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All the operations for &lt;code class=&quot;language-text&quot;&gt;users&lt;/code&gt; go into the users subdomain.&lt;/li&gt;
&lt;li&gt;All the operations for &lt;code class=&quot;language-text&quot;&gt;movies&lt;/code&gt; go into the movies subdomain.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;filename&quot;&gt;users.schema&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Query&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;orderBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;_UserOrdering&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Mutation&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;CreateUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; User
  &lt;span class=&quot;token attr-name&quot;&gt;UpdateUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; User
  &lt;span class=&quot;token attr-name&quot;&gt;DeleteUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; User
  &lt;span class=&quot;token attr-name&quot;&gt;AddUserRating&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _UserInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _MovieInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _RatedInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _AddUserRatedPayload
  &lt;span class=&quot;token attr-name&quot;&gt;RemoveUserRating&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _UserInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _MovieInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _RemoveUserRatedPayload
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;filename&quot;&gt;movies.schema&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Query&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;Movie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;movieId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;orderBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;_MovieOrdering&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Movie&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;Actor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;actorId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;orderBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;_ActorOrdering&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Actor&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Mutation&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;CreateMovie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;movieId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movie
  &lt;span class=&quot;token attr-name&quot;&gt;UpdateMovie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;movieId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movie
  &lt;span class=&quot;token attr-name&quot;&gt;DeleteMovie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;movieId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movie
  &lt;span class=&quot;token attr-name&quot;&gt;AddMovieActors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _ActorInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _MovieInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _AddMovieActorsPayload
  &lt;span class=&quot;token attr-name&quot;&gt;RemoveMovieActors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _ActorInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _MovieInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _RemoveMovieActorsPayload
  &lt;span class=&quot;token attr-name&quot;&gt;AddMovieRatings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _UserInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _MovieInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _RatingInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _AddMovieRatingsPayload
  &lt;span class=&quot;token attr-name&quot;&gt;CreateActor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;actorId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Actor
  &lt;span class=&quot;token attr-name&quot;&gt;UpdateActor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;actorId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Actor
  &lt;span class=&quot;token attr-name&quot;&gt;DeleteActor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;actorId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Actor
  &lt;span class=&quot;token attr-name&quot;&gt;AddActorMovies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _ActorInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _MovieInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _AddActorMoviesPayload
  &lt;span class=&quot;token attr-name&quot;&gt;RemoveActorMovies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _ActorInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _MovieInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _RemoveActorMoviesPayload
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There&apos;s still references between subdomains, and that&apos;s ok, because in software, we eventually need to connect pieces together.&lt;/p&gt;
&lt;p&gt;That said, it&apos;s a good idea to be explicit about those relationships- this is where tools like &lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/federation/introduction/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=nested_resolvers&quot;&gt;Apollo Federation&lt;/a&gt; come in handy because we can compose schemas and be precise about where fields are resolved from between services. &lt;/p&gt;
&lt;h3 id=&quot;Mutations&quot; style=&quot;position:relative;&quot;&gt;Mutations&lt;a href=&quot;#Mutations&quot; aria-label=&quot;Mutations permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Unfortunately, the story of nested resolvers for &lt;strong&gt;mutations&lt;/strong&gt; is a lot shorter. See &lt;a href=&quot;https://github.com/graphql/graphql-js/issues/221#issuecomment-568894704&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;https://github.com/apollographql/apollo-server/issues/3635&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Solutions&quot; style=&quot;position:relative;&quot;&gt;Solutions&lt;a href=&quot;#Solutions&quot; aria-label=&quot;Solutions permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&apos;s look at two approaches to remedy our design issue.&lt;/p&gt;
&lt;h3 id=&quot;1-Enforcing-a-GraphQL-operation-naming-pattern-for-both-queries-and-mutations&quot; style=&quot;position:relative;&quot;&gt;1. Enforcing a GraphQL-operation naming pattern for both queries and mutations&lt;a href=&quot;#1-Enforcing-a-GraphQL-operation-naming-pattern-for-both-queries-and-mutations&quot; aria-label=&quot;1 Enforcing a GraphQL operation naming pattern for both queries and mutations permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Best for &lt;em&gt;modular monolith&lt;/em&gt; applications where several subdomains are housed from within the same project (or in fancy DDD-talk, the same bounded context). &lt;/p&gt;
&lt;p&gt;With a modular monolith, &lt;code class=&quot;language-text&quot;&gt;users&lt;/code&gt; might be folder with everything related to &lt;code class=&quot;language-text&quot;&gt;users&lt;/code&gt;, where &lt;code class=&quot;language-text&quot;&gt;movies&lt;/code&gt; is its own folder with everything related to &lt;code class=&quot;language-text&quot;&gt;movies&lt;/code&gt;, as per &lt;strong&gt;screaming architecture&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;solid-book-cta course-cta&quot;&gt;
  &lt;div class=&quot;solid-book-logo-container&quot;&gt;
    &lt;img src=&quot;/img/resources/solid-book/book-logo.png&quot;/&gt;
  &lt;/div&gt;
  &lt;p&gt;&lt;a href=&quot;https://github.com/stemmlerjs/ddd-forum&quot;&gt;DDDForum&lt;/a&gt;, the app that we build at the end of &lt;a href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt; using Domain-Driven Design, is a modular monolith.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Suggested by @dncrews on GitHub, he suggests using the following GraphQL-operation naming pattern.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;primaryResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;SecondaryResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Updating the previous schema with this pattern may make it look like this.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;graphql.schema&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Mutation&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# Movies subdomain&lt;/span&gt;
  movieCreate
  movieUpdate
  movieDelete
  movieAddActor
  movieAddActors
  movieRemoveActor
  movieRemoveActors
  movieAddRatings
  actorCreate
  actorUpdate
  actorDelete

  &lt;span class=&quot;token comment&quot;&gt;# Users subdomain&lt;/span&gt;
  userCreate
  userUpdate
  userDelete
  userAddRating
  userRemoveRating
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It&apos;s not the perfect solution, but it&apos;s &lt;em&gt;good enough&lt;/em&gt; for many use cases.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Modularizing your schema&lt;/b&gt;: If you&apos;re not into having everything in one file, there are several ways you can modularize your GraphQL schema. Two popular tools are &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/Urigo/merge-graphql-schemas&quot;&gt;merge-graphql-schemas&lt;/a&gt; and &lt;a href=&quot;https://github.com/Urigo/graphql-modules&quot;&gt;graphql-modules&lt;/a&gt;, though I&apos;ve also resorted to simple string interpolation with Apollo Server.&lt;/p&gt;
&lt;h3 id=&quot;2-Federated-services&quot; style=&quot;position:relative;&quot;&gt;2. Federated services&lt;a href=&quot;#2-Federated-services&quot; aria-label=&quot;2 Federated services permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you&apos;re part of a larger organization, and other teams are can take ownership of their own GraphQL endpoints for their respective services, &lt;strong&gt;Apollo Federation&lt;/strong&gt; is a good idea.&lt;/p&gt;
&lt;p&gt;With Federation, we can get that &lt;strong&gt;separation of concerns&lt;/strong&gt; at the service level by delegating operations to the appropriate GraphQL endpoint in the organization using an Apollo Gateway. Here&apos;s the configuration of an Apollo Gateway.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;gateway.ts&lt;/div&gt; 
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; gateway &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ApolloGateway&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  serviceList&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;accounts&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;http://localhost:4001&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;products&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;http://localhost:4002&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;reviews&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;http://localhost:4003&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; server &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ApolloServer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; gateway &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;Configuration of an Apollo Gateway to implement a federated GraphQL architecture.&lt;/p&gt;
&lt;p&gt;In a Federated architecture, we can use the &lt;code class=&quot;language-text&quot;&gt;@provides&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;@key&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;@external&lt;/code&gt; directives to &lt;strong&gt;compose schemas&lt;/strong&gt;, be explicit about the relationships between services, and define which service is responsible for resolving a field in question.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;reviews.schema&lt;/div&gt; 
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Review&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String
  &lt;span class=&quot;token attr-name&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token directive function&quot;&gt;@provides&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;username&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Product
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

extend &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token directive function&quot;&gt;@key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;token directive function&quot;&gt;@external&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;reviews&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Review&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

extend &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;token directive function&quot;&gt;@key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;upc&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;upc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;token directive function&quot;&gt;@external&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;reviews&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Review&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Clone and try out the &lt;a href=&quot;https://github.com/apollographql/federation-demo&quot;&gt;Apollo Federation Demo&lt;/a&gt; if you&apos;re interested in this approach. To learn more about how it works and how to get started, check out &lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/federation/introduction/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=nested_resolvers&quot;&gt;the docs&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In order to achieve true separation of concerns at the service level, try out Apollo Federation.&lt;/p&gt;
&lt;p&gt;If you&apos;re working on a smaller project or working in a monolith, consider enforcing a naming pattern with the &lt;em&gt;namespace&lt;/em&gt; (subdomain) at the front of the GraphQL operation.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to Get the Currently Playing Song using the Spotify Node.js API & TypeScript]]></title><description><![CDATA[Intro When I first started building khalilstemmler.com, I stubbed out a component to present the current song that I was listening to on…]]></description><link>https://khalilstemmler.com/articles/tutorials/getting-the-currently-playing-song-spotify/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/tutorials/getting-the-currently-playing-song-spotify/</guid><pubDate>Sat, 22 Feb 2020 04:05:26 GMT</pubDate><content:encoded>&lt;h2 id=&quot;Intro&quot; style=&quot;position:relative;&quot;&gt;Intro&lt;a href=&quot;#Intro&quot; aria-label=&quot;Intro permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When I first started building &lt;a href=&quot;https://khalilstemmler.com&quot;&gt;khalilstemmler.com&lt;/a&gt;, I stubbed out a component to present the current song that I was listening to on Spotify. Y&apos;know, I just wanted to add a neat little feature to make the site a little bit more unique.&lt;/p&gt;
&lt;p&gt;Fast forward eight months, and it&apos;s still not hooked up. After about four attempts, I&apos;ve finally gotten the hard part down (integrating with the API). At some point, I might code the React component.&lt;/p&gt;
&lt;p&gt;This fun Spotify feature is part of my &lt;a href=&quot;https://github.com/stemmlerjs/stemmlerjs-graph&quot;&gt;Personal Data Graph&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;The reason I need a Personal Data Graph for this feature is, to fetch authenticated user resources from Spotify, the service that asks for the data needs to be, well- authenticated... as &lt;em&gt;me&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The docs from &lt;a href=&quot;https://developer.spotify.com/documentation/general/guides/authorization-guide/&quot;&gt;Spotify&apos;s Authorization Guide&lt;/a&gt; told me that I needed to use the &lt;a href=&quot;https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow&quot;&gt;Authorization Code&lt;/a&gt; approach, one of 3, to make this work.&lt;/p&gt;
&lt;p&gt;I&apos;m going to plow through this process and show you, very imperatively, the steps involved to authenticate a backend service to act on your behalf to fetch your currently playing song from Spotify.&lt;/p&gt;
&lt;h2 id=&quot;Prerequisites&quot; style=&quot;position:relative;&quot;&gt;Prerequisites&lt;a href=&quot;#Prerequisites&quot; aria-label=&quot;Prerequisites permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You&apos;re going to need to be using Node version 10x or higher for this to work. The reason for that is because the code that talks to Spotify relies on the &lt;code class=&quot;language-text&quot;&gt;URLSearchParams&lt;/code&gt; global.&lt;/p&gt;
&lt;h2 id=&quot;Installation-and-Setup&quot; style=&quot;position:relative;&quot;&gt;Installation and Setup&lt;a href=&quot;#Installation-and-Setup&quot; aria-label=&quot;Installation and Setup permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Clone or fork my repo over at &lt;a href=&quot;https://github.com/stemmlerjs/stemmlerjs-graph&quot;&gt;https://github.com/stemmlerjs/stemmlerjs-graph&lt;/a&gt; to follow along.&lt;/p&gt;
&lt;p&gt;Run the following commands to clone, install, and set up the project.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone git@github.com:stemmlerjs/stemmlerjs-graph.git
&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; stemmlerjs-graph
&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; .env.template .env&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Creating-a-Spotify-Developers-Account&quot; style=&quot;position:relative;&quot;&gt;Creating a Spotify Developers Account&lt;a href=&quot;#Creating-a-Spotify-Developers-Account&quot; aria-label=&quot;Creating a Spotify Developers Account permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Go to the &lt;a href=&quot;https://developer.spotify.com/dashboard/login&quot;&gt;Spotify Developers Dashboard&lt;/a&gt; and sign up for an account.&lt;/p&gt;
&lt;p&gt;When you&apos;re all signed up, you&apos;ll get to the Spotify Developers Dashboard that shows your applications. Click &quot;Create An App&quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tutorials/spotify/1-dashboard.png&quot; alt=&quot;&amp;#x22;Spotify Dashboard&amp;#x22;&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Spotify Developers Dashboard. You won&apos;t have an application already when you sign up the first time.&lt;/p&gt;
&lt;p&gt;Follow the prompts and select &lt;em&gt;Non-Commercial&lt;/em&gt; for the type of integration that we&apos;re creating (if you are creating a non-commercial app, that is).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tutorials/spotify/2-creating-app.png&quot; alt=&quot;&amp;#x22;Creating a new app&amp;#x22;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tutorials/spotify/3-non-commercial.png&quot; alt=&quot;&amp;#x22;Finishing registration&amp;#x22;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;Getting-your-Client-ID-and-Client-Secret&quot; style=&quot;position:relative;&quot;&gt;Getting your Client ID and Client Secret&lt;a href=&quot;#Getting-your-Client-ID-and-Client-Secret&quot; aria-label=&quot;Getting your Client ID and Client Secret permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When you log in, you should be able to see your Client ID. Underneath it, you can click to see your Client Secret.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tutorials/spotify/4-client-id-secret.png&quot; alt=&quot;&amp;#x22;Access Code and Secret Access Code&amp;#x22;&quot;&gt;&lt;/p&gt;
&lt;p&gt;First homework on the repo you cloned is to go into the &lt;code class=&quot;language-text&quot;&gt;.env&lt;/code&gt; file and supply the Client ID and Client Secret into the file for &lt;code class=&quot;language-text&quot;&gt;SPOTIFY_CLIENT_ID&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;SPOTIFY_CLIENT_SECRET&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;.env&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;SPOTIFY_CLIENT_SECRET&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# paste here&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;SPOTIFY_CLIENT_SECRET&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# paste here as well :-)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Setting-up-our-application&quot; style=&quot;position:relative;&quot;&gt;Setting up our application&lt;a href=&quot;#Setting-up-our-application&quot; aria-label=&quot;Setting up our application permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now we need to configure the application with the &lt;strong&gt;website&lt;/strong&gt; and &lt;strong&gt;redirect URI&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;On the dashboard page, click &quot;Edit Settings&quot;, and a modal should appear.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tutorials/spotify/5-configure-app.png&quot; alt=&quot;&amp;#x22;Finishing registration&amp;#x22;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Configuring-the-Website&quot; style=&quot;position:relative;&quot;&gt;Configuring the Website&lt;a href=&quot;#Configuring-the-Website&quot; aria-label=&quot;Configuring the Website permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For &lt;code class=&quot;language-text&quot;&gt;website&lt;/code&gt;, you don&apos;t need to have a website up and running yet, so just put in the name of a website that you own. &lt;/p&gt;
&lt;p&gt;If you don&apos;t own a website, you can use &lt;code class=&quot;language-text&quot;&gt;google.com&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Configuring-the-Redirect-URI&quot; style=&quot;position:relative;&quot;&gt;Configuring the Redirect URI&lt;a href=&quot;#Configuring-the-Redirect-URI&quot; aria-label=&quot;Configuring the Redirect URI permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is where Spotify sends us after we&apos;ve logged in. They send us to the URL that we supply, but also give us back an &lt;strong&gt;authorization code&lt;/strong&gt;. &lt;em&gt;We use that authorization code to get an &lt;strong&gt;access&lt;/strong&gt; and &lt;strong&gt;refresh token&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If you have a website, you can put &lt;em&gt;any URL from your domain&lt;/em&gt; here, and Spotify will redirect us there after logging in.&lt;/p&gt;
&lt;p&gt;If you &lt;em&gt;don&apos;t have a website&lt;/em&gt;, again- that&apos;s OK, we can use &lt;code class=&quot;language-text&quot;&gt;http://google.com/callback&lt;/code&gt; or something, but do understand that the domain that owns the website that we redirect to is fully capable of reading the &lt;strong&gt;authorization code&lt;/strong&gt; we receive.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;When you enter your Redirect URI, don&apos;t forget to press the &quot;Add&quot; button beside the URL, and THEN click &quot;Save&quot;. That&apos;s how attempt #1 of hooking this up failed for me - though you&apos;re much smarter so that won&apos;t happen to you.&lt;/p&gt;
&lt;p&gt;Whatever you&apos;ve provided as the Redirect URI, make sure to update the &lt;code class=&quot;language-text&quot;&gt;.env&lt;/code&gt; with this as well.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;.env&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;span class=&quot;token assign-left variable&quot;&gt;SPOTIFY_REDIRECT_URL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;https://khalilstemmler.com/callback &lt;span class=&quot;token comment&quot;&gt;# For example&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Getting-the-initial-Authorization-Code&quot; style=&quot;position:relative;&quot;&gt;Getting the initial Authorization Code&lt;a href=&quot;#Getting-the-initial-Authorization-Code&quot; aria-label=&quot;Getting the initial Authorization Code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Take this URL and substitute your Client ID and Redirect URI, where I&apos;ve placed &lt;code class=&quot;language-text&quot;&gt;PASTE_HERE&lt;/code&gt;, then paste the entire link into your browser. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;https://accounts.spotify.com/authorize?client_id=PASTE_HERE&amp;amp;
response_type=code&amp;amp;redirect_uri=PASTE_HERE&amp;amp;
scope=user-read-private%20user-read-currently-playing&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When you paste the link in your browser, you&apos;ll be asked to log in using your Facebook or email. Do that. &lt;/p&gt;
&lt;p&gt;Successfully logging in will bring you to this page that asks you to confirm the type of data that we&apos;re asking for. The &lt;a href=&quot;https://developer.spotify.com/documentation/general/guides/scopes/&quot;&gt;authorization scope&lt;/a&gt; that we&apos;re interested in is being able to see the user&apos;s currently playing song. Click &quot;agree&quot; here.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tutorials/spotify/6-accept-scope.png&quot; alt=&quot;&amp;#x22;Accept scope&amp;#x22;&quot;&gt;&lt;/p&gt;
&lt;p&gt;After clicking &quot;agree&quot;, we&apos;ll get sent to the redirect URI that we passed in earlier, but with our &lt;strong&gt;authorization code&lt;/strong&gt; as a &lt;code class=&quot;language-text&quot;&gt;code&lt;/code&gt; parameter in the &lt;strong&gt;resulting URL&lt;/strong&gt; (check the URL bar).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tutorials/spotify/7-redirected-url.png&quot; alt=&quot;&amp;#x22;Finishing registration&amp;#x22;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We&apos;re going to want whatever comes after &lt;code class=&quot;language-text&quot;&gt;?code=&lt;/code&gt; in the URL, so copy that.&lt;/p&gt;
&lt;h2 id=&quot;Using-the-Authorization-Code-to-get-an-Access-Token-and-the-Refresh-Token&quot; style=&quot;position:relative;&quot;&gt;Using the Authorization Code to get an Access Token and the Refresh Token&lt;a href=&quot;#Using-the-Authorization-Code-to-get-an-Access-Token-and-the-Refresh-Token&quot; aria-label=&quot;Using the Authorization Code to get an Access Token and the Refresh Token permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the root of the repository, run the following script with the code you copied from the URL.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run get-refresh-token &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;paste-your-code-here&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This will ask for a &lt;strong&gt;permanent refresh token&lt;/strong&gt; that we can use to make subsequent requests to the API and never have to worry about logging in again (that&apos;s dope).&lt;/p&gt;
&lt;p&gt;If all goes well, console output should look like this.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tutorials/spotify/8-get-refresh-token-script.png&quot; alt=&quot;&amp;#x22;Getting the refresh token using a script&amp;#x22;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Copy the refresh token that was emitted to the console into the &lt;code class=&quot;language-text&quot;&gt;.env&lt;/code&gt; file.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;.env&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;span class=&quot;token assign-left variable&quot;&gt;SPOTIFY_REFRESH_TOKEN&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Paste the refresh token that we just got here&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A couple of things to note if this doesn&apos;t work for you.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You have to run this script within &lt;em&gt;roughly&lt;/em&gt; a minute of getting the &lt;strong&gt;authorization code&lt;/strong&gt; from Spotify. This is a &lt;em&gt;security by opportunity&lt;/em&gt;- they reduce the total amount of time that someone can use that code hanging out in the open. If you get a 400 error, go back to &lt;strong&gt;Getting the initial Authorization Code&lt;/strong&gt; and paste the link again to generate a new &lt;strong&gt;authorization code&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;It will also fail if you&apos;ve forgotten to supply the &lt;code class=&quot;language-text&quot;&gt;SPOTIFY_CLIENT_ID&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;SPOTIFY_CLIENT_SECRET&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;SPOTIFY_REDIRECT_URL&lt;/code&gt; values.&lt;/li&gt;
&lt;li&gt;The last reason this might fail is if you&apos;re not running Node version 10 or higher.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Getting-the-currently-playing-song-via-GraphQL-Playground&quot; style=&quot;position:relative;&quot;&gt;Getting the currently playing song via GraphQL Playground&lt;a href=&quot;#Getting-the-currently-playing-song-via-GraphQL-Playground&quot; aria-label=&quot;Getting the currently playing song via GraphQL Playground permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://github.com/stemmlerjs/stemmlerjs-graph&quot;&gt;the repo&lt;/a&gt;, I&apos;ve already gone and done all the hard work of setting up a GraphQL server, defining the schema, and mapping the API results to a song type.&lt;/p&gt;
&lt;p&gt;The action happens in &lt;a href=&quot;https://github.com/stemmlerjs/stemmlerjs-graph/blob/master/src/modules/spotify/services/spotifyService.ts&quot;&gt;spotifyService.ts&lt;/a&gt; which you can peruse if you like. &lt;/p&gt;
&lt;p&gt;If you&apos;d like to play around with the graph via GraphQL playground, run:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run start&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then go to &lt;code class=&quot;language-text&quot;&gt;http://localhost:4000/&lt;/code&gt;, fire up your Spotify, play some music, and then run this query to see the results.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  spotifyGetCurrentSongPlaying &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    artist &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      name
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    title
    previewUrl
    externalUrl
    currentProgress
  	album &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      name
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Voila!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/tutorials/spotify/9-playground.png&quot; alt=&quot;&amp;#x22;Getting the refresh token using a script&amp;#x22;&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you&apos;re interested in my terrible music taste, pop over to &lt;a href=&quot;https://stemmlerjs-graph.netlify.com/&quot;&gt;stemmlerjs-graph.netlify.com&lt;/a&gt; and see what I&apos;m listening to currently.&lt;/p&gt;
&lt;p&gt;That&apos;s it! I hope this helps someone.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to Build a Compiler?]]></title><description><![CDATA[Today, in the Advanced JavaScript Developers group, someone asked the question: Musing from a Noob: so if you were to write a translator…]]></description><link>https://khalilstemmler.com/blogs/thoughts/building-a-compiler/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/thoughts/building-a-compiler/</guid><pubDate>Mon, 17 Feb 2020 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Today, in the &lt;a href=&quot;https://www.facebook.com/groups/advancedjavascript/&quot;&gt;Advanced JavaScript Developers group&lt;/a&gt;, someone asked the question:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Musing from a Noob: so if you were to write a translator from one language to another, say JS to Java or something arbitrary, would that translator be written almost entirely in like regular expressions or something? My google-fu is solid, but I&apos;m trying to get some professional opinions first.... What y&apos;all think?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&apos;m no professional in compiler development (I never got a chance to take Brock University&apos;s awesome compiler course), but I once wrote a LISP interpreter in Java (takes in some LISP code and executes it).&lt;/p&gt;
&lt;p&gt;For this, you might be able to hack your way through it with regular expressions, but &lt;em&gt;I think&lt;/em&gt; the proper way is to build an &lt;a href=&quot;https://en.wikipedia.org/wiki/Abstract_syntax_tree&quot;&gt;Abstract Syntax Tree&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In all programming languages, there&apos;s the concept of a &lt;a href=&quot;https://en.wikipedia.org/wiki/Context-free_grammar&quot;&gt;grammar&lt;/a&gt;. The grammar is something that defines all legal expressions in a language (much like English does).&lt;/p&gt;
&lt;p&gt;For example, in JavaScript, we&apos;re allowed to do:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But we can&apos;t do:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; x y z &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The grammar that &lt;em&gt;formalizes&lt;/em&gt; this might look something like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;[variable type] [variable name] = [value]&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we didn&apos;t follow that rule in the second example.&lt;/p&gt;
&lt;p&gt;If languages each have a set of grammar rules, and those rules are &lt;strong&gt;all the legal expressions&lt;/strong&gt;, then there are primarily two parts to building a compiler.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Establish the language rules (grammar)&lt;/li&gt;
&lt;li&gt;Be able to read a file, parse it, then build an validate an Abstract Syntax Tree from that grammar. If you can&apos;t build the syntax tree, it&apos;s because some grammar is wrong (this is the concept of a syntax error).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There&apos;s also the validation of the tree itself. &lt;/p&gt;
&lt;p&gt;For example, in Java, for a single tree, where a tree is a file (a program, like myApp.java), you&apos;re only allowed to have the &lt;code class=&quot;language-text&quot;&gt;public static void main (String[] args)&lt;/code&gt; once in the program, because that&apos;s the entry point.&lt;/p&gt;
&lt;p&gt;So &lt;em&gt;I think&lt;/em&gt; in order to PROPERLY do this conversion, you need to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Build the grammar for JavaScript&lt;/li&gt;
&lt;li&gt;Build the grammar for Java&lt;/li&gt;
&lt;li&gt;Know what the conversion rules from one grammar to the other are&lt;/li&gt;
&lt;li&gt;Build the syntax tree for JS code&lt;/li&gt;
&lt;li&gt;For each node (or a group of nodes) in the tree, run it against the conversion rules for Java and build a new syntax tree (a Java one).&lt;/li&gt;
&lt;li&gt;Convert the syntax tree to Java source code!&lt;/li&gt;
&lt;li&gt;(optional) run it through a prettier thing to make it look clean :p&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Definitely leave a comment below if you know a bit about the subject, you&apos;ve built a compiler before, or you have some useful resources for others.&lt;/p&gt;
&lt;h2 id=&quot;Resources&quot; style=&quot;position:relative;&quot;&gt;Resources&lt;a href=&quot;#Resources&quot; aria-label=&quot;Resources permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I found this page, &lt;a href=&quot;https://en.wikibooks.org/wiki/Introduction_to_Programming_Languages/Grammars?fbclid=IwAR0nLkq2rIAyA5DbDRHBXYpHWsNo21XYas-7GjeUe82G-DWtdAydk8oeBys&quot;&gt;Introduction to Programming Languages/Grammars&lt;/a&gt;. It seems really useful.&lt;/p&gt;
&lt;p&gt;There&apos;s also &lt;a href=&quot;https://babeljs.io/&quot;&gt;Babel&lt;/a&gt;, a modern JavaScript compiler that you might have used. I suspect peeking at the source code here would be insightful :)&lt;/p&gt;
&lt;p&gt;Other stuff:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[Free] &lt;a href=&quot;https://www.craftinginterpreters.com/the-lox-language.html&quot;&gt;https://www.craftinginterpreters.com/the-lox-language.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[Paid, but the content is really good apparently!] &lt;a href=&quot;https://coded-classes.dpdcart.com/product/81271&quot;&gt;https://coded-classes.dpdcart.com/product/81271&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Ensuring Sequelize Hooks Always Get Run]]></title><description><![CDATA[Intro In "Decoupling Logic with Domain Events [Guide] - Domain-Driven Design w/ TypeScript", we use Sequelize Hooks to decouple business…]]></description><link>https://khalilstemmler.com/blogs/sequelize/hooks/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/sequelize/hooks/</guid><pubDate>Sun, 02 Feb 2020 15:04:10 GMT</pubDate><content:encoded>&lt;h2 id=&quot;Intro&quot; style=&quot;position:relative;&quot;&gt;Intro&lt;a href=&quot;#Intro&quot; aria-label=&quot;Intro permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In &quot;&lt;a href=&quot;/articles/typescript-domain-driven-design/chain-business-logic-domain-events/&quot;&gt;Decoupling Logic with Domain Events [Guide] - Domain-Driven Design w/ TypeScript&lt;/a&gt;&quot;, we use &lt;a href=&quot;https://sequelize.org/master/manual/hooks.html&quot;&gt;Sequelize Hooks&lt;/a&gt; to decouple business logic, allowing the system to &lt;strong&gt;respond to events&lt;/strong&gt; in a fashion similar to the &lt;em&gt;Observer Pattern&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Sequelize hooks are places we can write callbacks that get invoked at key points in time like &lt;code class=&quot;language-text&quot;&gt;afterCreate&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;afterDestroy&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;afterUpdate&lt;/code&gt;, and more.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;infra/sequelize/hooks/index.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; models &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../models&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; DomainEvents &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../core/domain/events/DomainEvents&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../core/domain/UniqueEntityID&quot;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;dispatchEventsCallback&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; primaryKeyField&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; aggregateId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;model&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;primaryKeyField&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  DomainEvents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dispatchEventsForAggregate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aggregateId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createHooksForAggregateRoots&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; User &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models

  User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addHook&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;afterCreate&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;m&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dispatchEventsCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;user_id&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addHook&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;afterDestroy&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;m&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dispatchEventsCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;user_id&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addHook&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;afterUpdate&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;m&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dispatchEventsCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;user_id&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addHook&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;afterSave&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;m&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dispatchEventsCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;user_id&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addHook&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;afterUpsert&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;m&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dispatchEventsCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;user_id&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In Domain-Driven Design, after a transaction completes, we want to execute &lt;a href=&quot;/articles/typescript-domain-driven-design/chain-business-logic-domain-events/&quot;&gt;domain event handlers&lt;/a&gt; in order to decide whether we should invoke any follow up commands or not.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;forum/subscriptions/afterUserCreated.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserCreated &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../users/domain/events/userCreated&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IHandle &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../shared/domain/events/IHandle&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CreateMember &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../useCases/members/createMember/CreateMember&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; DomainEvents &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../shared/domain/events/DomainEvents&quot;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AfterUserCreated&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IHandle&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserCreated&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; createMember&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CreateMember

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;createMember&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CreateMember&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setupSubscriptions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;createMember &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; createMember
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;setupSubscriptions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Register to the domain event&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    DomainEvents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;onUserCreated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UserCreated&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;onUserCreated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserCreated&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; user &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; event

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;createMember&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;[AfterUserCreated]: Successfully executed CreateMember use case AfterUserCreated&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;[AfterUserCreated]: Failed to execute CreateMember use case AfterUserCreated.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;Sequelize Repository&lt;/a&gt;, where we deal with persistence logic, I have noticed that the hook callbacks do not get called &lt;strong&gt;if no new rows were created&lt;/strong&gt; and &lt;strong&gt;no columns were changed&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;In the &lt;code class=&quot;language-text&quot;&gt;save&lt;/code&gt; method of a repository, you&apos;ll find code where we rely on a &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;mapper&lt;/a&gt; to convert the domain object to the format necessary for Sequelize to save it. You&apos;ll also find code that determines if we&apos;re doing a &lt;code class=&quot;language-text&quot;&gt;create&lt;/code&gt; or an &lt;code class=&quot;language-text&quot;&gt;update&lt;/code&gt; based on the domain object&apos;s existence.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;forum/repos/implementations/sequelizePostRepo.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SequelizePostRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Post&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; PostModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Post&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; exists &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isNewPost &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;exists&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rawSequelizePost &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; PostMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toPersistence&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isNewPost&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; PostModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rawSequelizePost&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;saveComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;comments&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;savePostVotes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getVotes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;saveComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;comments&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;savePostVotes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getVotes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token comment&quot;&gt;// Persist the post model to the database &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; PostModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rawSequelizePost&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; post_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the highlighted lines, I expect the &lt;code class=&quot;language-text&quot;&gt;afterUpdate&lt;/code&gt; hook to get called, though it will not in scenarios where there were no are differences.&lt;/p&gt;
&lt;p&gt;To fix this, Sequelize&apos;s &lt;code class=&quot;language-text&quot;&gt;update&lt;/code&gt; method&apos;s second parameter configuration object allows you to pass in &lt;code class=&quot;language-text&quot;&gt;hooks: true&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;forum/repos/implementations/sequelizePostRepo.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; PostModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rawSequelizePost&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
  where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; post_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Be sure to include this to call hooks regardless&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// of anything changed or not.&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  hooks&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Doing this will ensure that the hooks get run everytime.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Domain-Driven GraphQL Schema Design using Event Storming]]></title><description><![CDATA[Introduction Designing your GraphQL schema is a potentially expensive task. It's potentially expensive because if we respect the principles…]]></description><link>https://khalilstemmler.com/articles/graphql/ddd/schema-design/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/graphql/ddd/schema-design/</guid><pubDate>Fri, 31 Jan 2020 22:04:10 GMT</pubDate><content:encoded>&lt;!-- You&apos;re in a post-apocalptic wasteland. After several hundreds of years, society is in the process of slowly rebuilding itself. Tribes and groups have started to form throughout your region, but none of them are talking to each other just yet. Members from the Northern Tribe have discovered transportation. But people are going hungry. Members from the Western Tribe are masters in agriculture. Your job is to assemble all the differen groups throughout your region, show them what they can do together, and save humanity. --&gt;
&lt;h2 id=&quot;Introduction&quot; style=&quot;position:relative;&quot;&gt;Introduction&lt;a href=&quot;#Introduction&quot; aria-label=&quot;Introduction permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Designing your GraphQL schema is a potentially expensive task.&lt;/p&gt;
&lt;p&gt;It&apos;s &lt;em&gt;potentially expensive&lt;/em&gt; because if we respect the &lt;a href=&quot;https://principledgraphql.com/&quot;&gt;principles of GraphQL&lt;/a&gt;, the (company-wide) GraphQL schema becomes the singular source of truth for our client applications, and the contract for our sever-side data sources. &lt;/p&gt;
&lt;p&gt;The single source of truth isn&apos;t exactly the type of thing you want to get terribly wrong the first time around.&lt;/p&gt;
&lt;p&gt;This sentiment is shared by expert GraphQL-r and developer from &lt;a href=&quot;https://twitter.com/PinterestEng&quot;&gt;Pinterest Engineering&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/engfragui&quot;&gt;Francesca Guiducci&lt;/a&gt;, who says to &quot;involve others when designing the GraphQL schema&quot; (via &lt;a href=&quot;https://www.netlify.com/blog/2020/01/21/advice-from-a-graphql-expert/&quot;&gt;Netlify, Jan 21st, 2019&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I&apos;m with Francesca on this one. Your GraphQL API is the language others use to build on top of your services, and if it doesn&apos;t come from a &lt;strong&gt;shared understanding&lt;/strong&gt; of the domain, some domain concepts could end up being really off. &lt;/p&gt;
&lt;p&gt;Designing a GraphQL schema is not usually something a single developer creates in isolation.&lt;/p&gt;
&lt;h3 id=&quot;Domain-Driven-GraphQL&quot; style=&quot;position:relative;&quot;&gt;Domain-Driven GraphQL?&lt;a href=&quot;#Domain-Driven-GraphQL&quot; aria-label=&quot;Domain Driven GraphQL permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven&lt;/a&gt; GraphQL means putting an effort into understanding the domain you work in, and using that knowledge to drive development against a model of the business that mimics how it works in the real world.&lt;/p&gt;
&lt;p&gt;Code that acts as a software representation of the business is more correct, more tolerant to change, has less inaccurate and undesireable side-effects, and can be understood by everyone.&lt;/p&gt;
&lt;p&gt;Often, developers are really good at &lt;em&gt;developing&lt;/em&gt;, but don&apos;t hold a great understanding of the &lt;em&gt;domain&lt;/em&gt;. To fix that, we can spend more time interacting with people who &lt;em&gt;do&lt;/em&gt; understand the domain. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/ddd/schema-design/talk-cap.png&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;You&apos;re probably more likely to find a rare unicorn strolling down your company office than you are to find someone who is both a GraphQL Expert AND a Domain Expert - from &lt;a target=&quot;_blank&quot; href=&quot;https://twitter.com/__xuorig__&quot;&gt;Marc-André Giroux&lt;/a&gt;&apos;s &lt;a target=&quot;_blank&quot; href=&quot;https://www.youtube.com/watch?v=pJamhW2xPYw&quot;&gt;talk at GraphQL Summit 2018&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;This post was inspired by a tweet I blasted out recently. It describes how we can stack our odds of success for building an accurate GraphQL schema by involving domain experts in a process called &lt;em&gt;Event Storming&lt;/em&gt;.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;🖼️Domain-Driven GraphQL Schema Design (in 6 tweets)👇&lt;a href=&quot;https://twitter.com/hashtag/graphQL?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#graphQL&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/eventstorming?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#eventstorming&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/dddesign?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#dddesign&lt;/a&gt; &lt;a href=&quot;https://t.co/5P2p0XzI2q&quot;&gt;pic.twitter.com/5P2p0XzI2q&lt;/a&gt;&lt;/p&gt;&amp;mdash; Khalil Stemmler (@stemmlerjs) &lt;a href=&quot;https://twitter.com/khalilstemmler/status/1220401521784954881?ref_src=twsrc%5Etfw&quot;&gt;January 23, 2020&lt;/a&gt;&lt;/blockquote&gt; &lt;script async src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;br/&gt;
&lt;p&gt;Let&apos;s talk about it.&lt;/p&gt;
&lt;h2 id=&quot;Event-Storming&quot; style=&quot;position:relative;&quot;&gt;Event Storming&lt;a href=&quot;#Event-Storming&quot; aria-label=&quot;Event Storming permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;By definition, &lt;em&gt;Event Storming&lt;/em&gt; is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A group or workshop-based modeling technique that brings stakeholders and developers together in order to understand the domain quickly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/ddd/schema-design/event-storming.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;It all started when a developer named &lt;a href=&quot;https://twitter.com/ziobrando&quot;&gt;Alberto Brandolini&lt;/a&gt; found himself short on time to organize a traditional UML use case design session with some clients. Thinking quickly, he improvised with some sticky notes, markers, and a whiteboard- inadvertently creating &lt;em&gt;Event Storming&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Today, &lt;em&gt;Event Storming&lt;/em&gt; has become something of a staple in the DDD community. &lt;/p&gt;
&lt;p&gt;It&apos;s a quick (and fun!) interactive design process that engages both developers and business-folk to learn the business &lt;strong&gt;and create a shared understanding of the problem domain&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;The result is either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a) A big-picture understanding of the domain (less precise but still very useful).&lt;/li&gt;
&lt;li&gt;b) 🔥A design-level understanding (more precise), which yields software artifacts (&lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;aggregates&lt;/a&gt;, commands, views, &lt;a href=&quot;/articles/typescript-domain-driven-design/chain-business-logic-domain-events/&quot;&gt;domain events&lt;/a&gt;) agreed on by both developers and domain experts that can be turned into rich domain layer code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By running an &lt;em&gt;Event Storming&lt;/em&gt; session, we end up answering a lot of questions and have all the pieces needed to construct a rich GraphQL schema.&lt;/p&gt;
&lt;h2 id=&quot;Using-an-Event-Storm-to-design-a-GraphQL-Schema&quot; style=&quot;position:relative;&quot;&gt;Using an Event Storm to design a GraphQL Schema&lt;a href=&quot;#Using-an-Event-Storm-to-design-a-GraphQL-Schema&quot; aria-label=&quot;Using an Event Storm to design a GraphQL Schema permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can use this approach in any context. If you&apos;ve been asked to build a new app, or you want to start to introduce GraphQL on an existing project, you can take the following approach.&lt;/p&gt;
&lt;h3 id=&quot;Step-1-Domain-Events&quot; style=&quot;position:relative;&quot;&gt;💡Step 1. Domain Events&lt;a href=&quot;#Step-1-Domain-Events&quot; aria-label=&quot;Step 1 Domain Events permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p class=&quot;special-quote&quot;&gt;Plot out all of the events that happen for the main story in your application as &lt;i&gt;past-tense&lt;/i&gt; verbs.&lt;/p&gt;
&lt;p&gt;For my Hackernews-like app, &lt;a href=&quot;https://github.com/stemmlerjs/ddd-forum/&quot;&gt;DDDForum.com&lt;/a&gt;, that looks like:&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;UserCreated&lt;/code&gt; =&gt; &lt;code class=&quot;language-text&quot;&gt;MemberCreated&lt;/code&gt; =&gt; &lt;code class=&quot;language-text&quot;&gt;PostCreated&lt;/code&gt; =&gt; &lt;code class=&quot;language-text&quot;&gt;CommentCreated&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;CommentUpvoted&lt;/code&gt;, etc.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/ddd/schema-design/1-domain-events.jpg&quot; alt=&quot;Domain Events&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Events drawn out chronologically on a timeline from left to right.&lt;/p&gt;
&lt;h3 id=&quot;Step-2-Commands&quot; style=&quot;position:relative;&quot;&gt;💡Step 2. Commands&lt;a href=&quot;#Step-2-Commands&quot; aria-label=&quot;Step 2 Commands permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p class=&quot;special-quote&quot;&gt;For each &lt;i&gt;Domain Event&lt;/i&gt;, write the &lt;i&gt;Command&lt;/i&gt; that causes it. These are your &lt;b&gt;GraphQL mutations&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;They should be in an imperative form. If you know the name of the role/actor that performs it, you can document that as well.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/ddd/schema-design/2-1-command.jpg&quot; alt=&quot;Commands&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Commands accompanying their respective Domain Event chronologically on a timeline from left to right.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/ddd/schema-design/2-2-command.jpg&quot; alt=&quot;Commands with Roles&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;If you know the actor, that can be documented as well. Here, we know that &lt;i&gt;Members&lt;/i&gt; are the only ones that are allowed to issue the &lt;i&gt;Create Post&lt;/i&gt; command.&lt;/p&gt;
&lt;h3 id=&quot;Step-3-Aggregates-write-models&quot; style=&quot;position:relative;&quot;&gt;💡Step 3. Aggregates (write models)&lt;a href=&quot;#Step-3-Aggregates-write-models&quot; aria-label=&quot;Step 3 Aggregates write models permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p class=&quot;special-quote&quot;&gt;For each &lt;i&gt;Command/Domain Event&lt;/i&gt; pair, identify the &lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;Aggregate (or write model)&lt;/a&gt; that they belong to.&lt;/p&gt;
&lt;p&gt;In &lt;em&gt;Event Storming&lt;/em&gt;, we normally place the &lt;em&gt;Aggregate (write model)&lt;/em&gt; above the &lt;i&gt;Command/Domain Event&lt;/i&gt; pair.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/ddd/schema-design/3-aggregate.jpg&quot; alt=&quot;Aggregates&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Commands accompanying their respective Domain Event chronologically on a timeline from left to right.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;Step-4-Enforce-boundaries--identify-top-level-fields&quot; style=&quot;position:relative;&quot;&gt;💡Step 4. Enforce boundaries &amp;#x26; identify top-level fields&lt;a href=&quot;#Step-4-Enforce-boundaries--identify-top-level-fields&quot; aria-label=&quot;Step 4 Enforce boundaries  identify top level fields permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p class=&quot;special-quote&quot;&gt;Identify the top-level GraphQL fields by applying &lt;a href=&quot;https://khalilstemmler.com/wiki/conways-law/&quot;&gt;Conway&apos;s Law&lt;/a&gt;. If you&apos;re building a &lt;i&gt;Modular Monolith&lt;/i&gt;, these will be your subdomains. If you&apos;re working with &lt;i&gt;Distributed Microservices&lt;/i&gt;, these will be your &lt;a target=&quot;_blank&quot; href=&quot;https://www.apollographql.com/docs/apollo-server/federation/introduction/?utm_source=khalil&amp;utm_medium=article&amp;utm_campaign=domain_driven_graphql_schema_design&quot;&gt;Federated GraphQL endpoints&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Segregate the &lt;em&gt;Events&lt;/em&gt;, &lt;em&gt;Commands&lt;/em&gt;, and &lt;em&gt;Aggregate&lt;/em&gt; groups from each other based on the relevant self-organizing teams that play a part in the story of our application.&lt;/p&gt;
&lt;p&gt;📖 This is probably the hardest and most misunderstood step. I&apos;ll create more documentation about this in the future. You may want to read about Conway&apos;s Law =&gt; (&lt;a href=&quot;https://khalilstemmler.com/wiki/conways-law/&quot;&gt;read here&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/ddd/schema-design/4-1-boundaries.jpg&quot; alt=&quot;Boundaries&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;The story often flows between several subdomains/bounded contexts. For example, when a &lt;i&gt;UserCreated&lt;/i&gt; event in the &lt;i&gt;Users&lt;/i&gt; subdomain gets fired off, we subscribe and immediately issue a &lt;i&gt;CreateMember&lt;/i&gt; command from the &lt;i&gt;Forum subdomain&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/ddd/schema-design/4-2-boundaries.jpg&quot; alt=&quot;Boundaries&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;Step-5-Identify-Views--Queries&quot; style=&quot;position:relative;&quot;&gt;💡Step 5. Identify Views / Queries&lt;a href=&quot;#Step-5-Identify-Views--Queries&quot; aria-label=&quot;Step 5 Identify Views  Queries permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p class=&quot;special-quote&quot;&gt;For each &lt;i&gt;Aggregate&lt;/i&gt;, identify all possible &lt;i&gt;Views (GraphQL queries)&lt;/i&gt; required in order to give users enough information to perform &lt;i&gt;Commands (GraphQL mutations)&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/ddd/schema-design/5-views.jpg&quot; alt=&quot;Views&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;p-classcaptionThe-iPosti-aggregate-has-several-different-viewsp&quot; style=&quot;position:relative;&quot;&gt;&lt;p class=&quot;caption&quot;&gt;The &lt;i&gt;Post&lt;/i&gt; aggregate has several different views.&lt;/p&gt;&lt;a href=&quot;#p-classcaptionThe-iPosti-aggregate-has-several-different-viewsp&quot; aria-label=&quot;p classcaptionThe iPosti aggregate has several different viewsp permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;6-Create-the-GraphQL-Schema&quot; style=&quot;position:relative;&quot;&gt;💡6. Create the GraphQL Schema&lt;a href=&quot;#6-Create-the-GraphQL-Schema&quot; aria-label=&quot;6 Create the GraphQL Schema permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p class=&quot;special-quote&quot;&gt;Finally, create our GraphQL Schema from the discovered &lt;i&gt;Commands (Mutations)&lt;/i&gt; and &lt;i&gt;Queries&lt;/i&gt;. &lt;/p&gt;
&lt;p&gt;In &lt;em&gt;Modular Monoliths&lt;/em&gt;, you can break the schema up into separate files by &lt;code class=&quot;language-text&quot;&gt;extend&lt;/code&gt;-ing the Query and Mutation or by using &lt;a href=&quot;https://github.com/Urigo/graphql-modules&quot;&gt;graphql-modules&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;infra/http/graphql/schemas/forum.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostType&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  text
  link
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Post&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String
  &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String
  &lt;span class=&quot;token attr-name&quot;&gt;createdAt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; DateTime
  &lt;span class=&quot;token attr-name&quot;&gt;memberPostedBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Member
  &lt;span class=&quot;token attr-name&quot;&gt;numComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int
  &lt;span class=&quot;token attr-name&quot;&gt;points&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int
  &lt;span class=&quot;token attr-name&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String
  &lt;span class=&quot;token attr-name&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String
  &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; PostType
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;memberId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String
  &lt;span class=&quot;token attr-name&quot;&gt;reputation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int
  &lt;span class=&quot;token attr-name&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; User
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostCollectionResult&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;cursor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;hasMore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Boolean&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;launches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Launch&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

extend &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Query&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;postById&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ID&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Post
  &lt;span class=&quot;token attr-name&quot;&gt;postBySlug&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Post
  &lt;span class=&quot;token attr-name&quot;&gt;popularPosts&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;pageSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; PostCollectionResult
  &lt;span class=&quot;token attr-name&quot;&gt;recentPosts&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;pageSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; PostCollectionResult
  &lt;span class=&quot;token attr-name&quot;&gt;memberById&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Member
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

extend &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Mutation&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;createPost&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CreatePostInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CreatePostPayload
  &lt;span class=&quot;token attr-name&quot;&gt;createMember&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CreateMemberInput&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CreateMemberPayload
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
`&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For Federated GraphQL architectures, you can compose schemas using the &lt;code class=&quot;language-text&quot;&gt;@key&lt;/code&gt; directive that comes from &lt;code class=&quot;language-text&quot;&gt;@apollo/federation&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Final-thoughts&quot; style=&quot;position:relative;&quot;&gt;Final thoughts&lt;a href=&quot;#Final-thoughts&quot; aria-label=&quot;Final thoughts permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Modeling-with-events-when-CRUD-doesnt-fit&quot; style=&quot;position:relative;&quot;&gt;Modeling with events when CRUD doesn&apos;t fit&lt;a href=&quot;#Modeling-with-events-when-CRUD-doesnt-fit&quot; aria-label=&quot;Modeling with events when CRUD doesnt fit permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is a controversial opinion, but one I feel strongly about arguing. I believe that most naturally occurring systems &lt;a href=&quot;/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;don&apos;t naturally fit within the rigid confines of CRUD&lt;/a&gt;. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Complex systems are everywhere we look.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;By definition, Julian Shapiro says that &quot;&lt;strong&gt;a system&lt;/strong&gt; is anything with multiple parts that &lt;strong&gt;depend on each other&lt;/strong&gt;.&quot;&lt;/p&gt;
&lt;p&gt;I&apos;m not just talking about software. Consider these &lt;em&gt;real world systems&lt;/em&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Getting started at a new job&lt;/strong&gt;: Applying to jobs, performing interviews, receiving offers, conducting negotiations, acceptances, paperwork, then (optional) relocation, onboarding/training.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Buying a condo&lt;/strong&gt;: Finding a place, getting approved for credit (if you don&apos;t get approved, you might have a new prerequisite goal - improve credit, earn capital, or ask relatives), making an offer, accepting an offer, signing paperwork, then making payments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Getting your driver&apos;s license&lt;/strong&gt;: (Optionally) attending driving school, booking the test, passing the test (or failing the test and re-booking), getting your picture taken, getting your temporary license, then getting your license mailed to you.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As human beings, these systems don&apos;t seem that complex in the real world. The reason is because we tend to tame the complexity of them and &lt;strong&gt;how we progress through them&lt;/strong&gt; by conceptualizing them as a series of &lt;strong&gt;events&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;For example, before you &lt;strong&gt;accept a job&lt;/strong&gt;, you need to have &lt;strong&gt;applied to jobs&lt;/strong&gt;, &lt;strong&gt;performed an interview&lt;/strong&gt;, and then gotten an &lt;strong&gt;offer&lt;/strong&gt;.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;See how those steps &lt;i&gt;depend&lt;/i&gt; on each other? While I wish I could always just jump to the &lt;i&gt;offer step&lt;/i&gt;, it&apos;s not possible.&lt;/p&gt;
&lt;p&gt;Software systems often serve the singular purpose of making life easier for humans by consolidating the number of events that require human intervention.&lt;/p&gt;
&lt;h3 id=&quot;div-classexpandable-sectionExamples-of-consolidated-systemsdiv-classexpandable-section-button-onclicktoggleExpandableSectionconsolidated-systemsdivdiv&quot; style=&quot;position:relative;&quot;&gt;&lt;div class=&quot;expandable-section&quot;&gt;Examples of consolidated systems&lt;div class=&quot;expandable-section-button&quot; onclick=&quot;toggleExpandableSection(&apos;consolidated-systems&apos;)&quot;&gt;+&lt;/div&gt;&lt;/div&gt;&lt;a href=&quot;#div-classexpandable-sectionExamples-of-consolidated-systemsdiv-classexpandable-section-button-onclicktoggleExpandableSectionconsolidated-systemsdivdiv&quot; aria-label=&quot;div classexpandable sectionExamples of consolidated systemsdiv classexpandable section button onclicktoggleExpandableSectionconsolidated systemsdivdiv permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div id=&quot;consolidated-systems&quot; class=&quot;expandable-section-content&quot;&gt;
  &lt;p&gt;These are examples of systems consolidated by software.&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://linkedin.com&quot;&gt;LinkedIn&lt;/a&gt; consolidates the system of making professional connections.&lt;/li&gt;
    &lt;li&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://facebook.com&quot;&gt;Facebook&lt;/a&gt; consolidates the system of maintaining personal friendships.&lt;/li&gt;
    &lt;li&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://uber.com&quot;&gt;Uber&lt;/a&gt; consolidates the system of on-demand based transportation like taxis.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[How I Write Testable Code | Khalil's Simple Methodology]]></title><description><![CDATA[Understanding how to write testable code is one of the biggest frustrations I had when I finished school and started working at my first…]]></description><link>https://khalilstemmler.com/articles/software-design-architecture/write-testable-code/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/software-design-architecture/write-testable-code/</guid><pubDate>Mon, 20 Jan 2020 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Understanding how to write testable code is one of the biggest frustrations I had when I finished school and started working at my first real-world job.&lt;/p&gt;
&lt;p&gt;Today, while working on a chapter in &lt;a href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt;, breaking down some code and picking apart everything wrong with it, I realized that several principles govern how I write code to be testable. &lt;/p&gt;
&lt;p&gt;In this article, I want to present you with a straightforward methodology you can apply to both front-end and back-end code for how to write testable code. &lt;/p&gt;
&lt;h2 id=&quot;Prerequisite-readings&quot; style=&quot;position:relative;&quot;&gt;Prerequisite readings&lt;a href=&quot;#Prerequisite-readings&quot; aria-label=&quot;Prerequisite readings permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You may want to read the following pieces beforehand. 😇&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;Dependency Injection &amp;#x26; Inversion Explained | Node.js w/ TypeScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/wiki/dependency-rule/&quot;&gt;The Dependency Rule&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/wiki/stable-dependency-principle/&quot;&gt;The Stable Dependency Principle - SDP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Dependencies-are-relationships&quot; style=&quot;position:relative;&quot;&gt;Dependencies are relationships&lt;a href=&quot;#Dependencies-are-relationships&quot; aria-label=&quot;Dependencies are relationships permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You may already know this, but the first thing to understand is that when we import or &lt;em&gt;even mention&lt;/em&gt; the name of another class, function, or variable from one class (let&apos;s call this the &lt;em&gt;source class&lt;/em&gt;), whatever was mentioned &lt;u&gt;becomes a dependency to the source class&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&quot;https://khalilstemmler.com/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;dependency inversion &amp;#x26; injection article&lt;/a&gt;, we looked at an example of a &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt; that needed access to a &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; to &lt;strong&gt;get all users&lt;/strong&gt;.&lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;controllers/userController.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../repos&apos;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Bad&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * @class UserController
 * @desc Responsible for handling API requests for the
 * /user route.
 **/&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Also bad.&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleGetUsers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; users &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUsers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; users &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The problem with this approach was that when we do this, we create a hard &lt;strong&gt;source-code dependency&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The relationship looks like the following:&lt;/p&gt;
&lt;img style=&quot;width: 100%;&quot; src=&quot;/img/blog/di-container/before-dependency-inversion.svg&quot;&gt;
&lt;p class=&quot;caption&quot;&gt;UserController relies directly on UserRepo.&lt;/p&gt;
&lt;p&gt;This means that if we ever wanted to test &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt;, we&apos;d need to bring &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; along for the ride as well. The thing about &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt;, though, is that it also brings a whole damn database connection with it as well. And that&apos;s no good.&lt;/p&gt;
&lt;p&gt;If we need to spin up a database to run unit tests, that makes all our unit tests slow.&lt;/p&gt;
&lt;p&gt;Ultimately, we can fix this by using &lt;strong&gt;dependency inversion&lt;/strong&gt;, putting an abstraction between the two dependencies.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Abstractions&lt;/b&gt; that can invert the flow of dependencies are either &lt;i&gt;interfaces&lt;/i&gt; or &lt;i&gt;abstract classes&lt;/i&gt;.&lt;/p&gt;
&lt;img style=&quot;width: 100%&quot; src=&quot;https://khalilstemmler.com/img/blog/di-container/after-dependency-inversion.svg&quot; /&gt;
&lt;p class=&quot;caption&quot;&gt;Using an interface to implement Dependency Inversion.&lt;/p&gt;
&lt;p&gt;This works by placing an abstraction (interface or abstract class) in between the dependency you want to import and the source class. The source class imports the abstraction, and remains testable because we can pass in &lt;em&gt;anything&lt;/em&gt; that has adhered to the contract of the abstraction, even if it&apos;s a &lt;em&gt;mock object&lt;/em&gt;.&lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;controllers/userController.ts&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IUserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../repos&apos;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Good! Refering to the abstraction.&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * @class UserController
 * @desc Responsible for handling API requests for the
 * /user route.
 **/&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// abstraction here&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// and here&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleGetUsers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; users &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUsers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; users &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In our scenario with &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt;, it now refers to an &lt;code class=&quot;language-text&quot;&gt;IUserRepo&lt;/code&gt; interface (which costs nothing) rather than referring to the potentially heavy &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; that carries a db connection with it everywhere it goes.&lt;/p&gt;
&lt;p&gt;If we wish to test the controller, we can satisfy the &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt;&apos;s need for an &lt;code class=&quot;language-text&quot;&gt;IUserRepo&lt;/code&gt; by substituting our db-backed &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; for an &lt;em&gt;in-memory implementation&lt;/em&gt;. We can create one like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InMemoryMockUserRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IUserRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// implement methods and properties&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;!-- We might not find a huge amount of utility running unit tests against a controller per say, but we most certainly would want to run tests against our application layer [use cases](/articles/enterprise-typescript-nodejs/application-layer-use-cases/), especially if we&apos;re doing [domain-driven design](/articles/domain-driven-design-intro/) and have a set of BDD-style test cases to test against &apos;em.

In [DDDForum](https://github.com/stemmlerjs/ddd-forum/), the example TypeScript + DDD project, there&apos;s a use case called `upvotePost`. We might want to test the use case given a scenario like this:

```text
Scenario: Khalil can&apos;t upvote his own post twice
  Given: I am logged in as Khalil
  And: My post exists
  And: I have already upvoted my own post
  And: My post has a score of 7
  When: I upvote my own post
  Then: My post should still have a score of 7
``` --&gt;
&lt;!-- &lt;p class=&quot;caption&quot;&gt;A test case written using Gherkin, the BDD-style structured language for describing how systems should behave at the business level.&lt;/p&gt; --&gt;
&lt;h2 id=&quot;The-methodology&quot; style=&quot;position:relative;&quot;&gt;The methodology&lt;a href=&quot;#The-methodology&quot; aria-label=&quot;The methodology permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&apos;s my thought process for keeping code testable. It all starts when you want to create a relationship from one class to another.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Start: You want to import or mention the name of a class from another file.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Question: do you care about being able to write tests against the &lt;em&gt;source class&lt;/em&gt; in the future?&lt;/p&gt;
&lt;p&gt;If &lt;strong&gt;no&lt;/strong&gt;, go ahead and import whatever it is because it doesn&apos;t matter.&lt;/p&gt;
&lt;p&gt;If &lt;strong&gt;yes&lt;/strong&gt;, consider the following restrictions. You may depend on the class only if it is &lt;em&gt;at least one&lt;/em&gt; of these:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The dependency is an abstraction (interface or abstract class).&lt;/li&gt;
&lt;li&gt;The dependency is from the same layer or an inner layer (see &lt;a href=&quot;https://khalilstemmler.com/wiki/dependency-rule/&quot;&gt;The Dependency Rule&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;It is a &lt;a href=&quot;https://khalilstemmler.com/wiki/stable-dependency-principle/&quot;&gt;stable dependency&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;If at &lt;em&gt;least one&lt;/em&gt; of these conditions passes, import the dependency- otherwise, don&apos;t.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Importing the dependency introduces the possibility that it will be hard to test that component in the future.&lt;/p&gt;
&lt;p&gt;Again, you can fix scenarios where the dependency breaks one of those rules by using &lt;a href=&quot;https://khalilstemmler.com/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;Dependency Inversion&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Front-end-example-React-w-TypeScript&quot; style=&quot;position:relative;&quot;&gt;Front-end example (React w/ TypeScript)&lt;a href=&quot;#Front-end-example-React-w-TypeScript&quot; aria-label=&quot;Front end example React w TypeScript permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What about front-end development?&lt;/p&gt;
&lt;p&gt;The same rules apply!&lt;/p&gt;
&lt;p&gt;Take this React component (pre-hooks) involving a &lt;em&gt;container component&lt;/em&gt; (inner layer concern) that depends on a &lt;code class=&quot;language-text&quot;&gt;ProfileService&lt;/code&gt; (outer layer - infra). &lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;containers/ProfileContainer.tsx&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ProfileService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./services&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// hard source-code dependency&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IProfileData &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./models&apos;&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;// stable dependency&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProfileContainerProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProfileContainerState&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  profileData&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IProfileData &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProfileContainer&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Component&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
  ProfileContainerProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
  ProfileContainerState
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; profileService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ProfileService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ProfileContainerProps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      profileData&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;profileService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProfileService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Bad.&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;componentDidMount&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; profileData&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IProfileData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;profileService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getProfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        profileData
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Ooops&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Im a profile container&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If &lt;code class=&quot;language-text&quot;&gt;ProfileService&lt;/code&gt; is something that makes network calls to a RESTful API, there&apos;s no way for us to test &lt;code class=&quot;language-text&quot;&gt;ProfileContainer&lt;/code&gt; and prevent it from making real API calls.&lt;/p&gt;
&lt;p&gt;We can fix this by doing two things:&lt;/p&gt;
&lt;h3 id=&quot;1-Putting-an-interface-in-between-the-ProfileService-and-ProfileContainer&quot; style=&quot;position:relative;&quot;&gt;1. Putting an interface in between the &lt;code class=&quot;language-text&quot;&gt;ProfileService&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;ProfileContainer&lt;/code&gt;&lt;a href=&quot;#1-Putting-an-interface-in-between-the-ProfileService-and-ProfileContainer&quot; aria-label=&quot;1 Putting an interface in between the ProfileService and ProfileContainer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;First, we create the abstraction and then ensure that &lt;code class=&quot;language-text&quot;&gt;ProfileService&lt;/code&gt; implements it.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;services/index.tsx&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IProfileData &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../models&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Create an abstraction&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IProfileService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token function-variable function&quot;&gt;getProfile&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IProfileData&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Implement the abstraction&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProfileService&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IProfileService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getProfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IProfileData&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;An abstraction for ProfileService in the form of an interface.&lt;/p&gt;
&lt;p&gt;Then we update &lt;code class=&quot;language-text&quot;&gt;ProfileContainer&lt;/code&gt; to rely on the abstraction instead.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;containers/ProfileContainer.tsx&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
  ProfileService&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  IProfileService &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./services&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// import interface&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IProfileData &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./models&apos;&lt;/span&gt; 

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProfileContainerProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProfileContainerState&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  profileData&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IProfileData &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProfileContainer&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Component&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
  ProfileContainerProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
  ProfileContainerState
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; profileService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IProfileService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ProfileContainerProps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      profileData&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;profileService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProfileService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Still bad though&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;componentDidMount&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; profileData&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IProfileData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;profileService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getProfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        profileData
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Ooops&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Im a profile container&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;2-Compose-a-ProfileContainer-with-a-HOC-that-contains-a-valid-IProfileService&quot; style=&quot;position:relative;&quot;&gt;2. Compose a &lt;code class=&quot;language-text&quot;&gt;ProfileContainer&lt;/code&gt; with a HOC that contains a valid &lt;code class=&quot;language-text&quot;&gt;IProfileService&lt;/code&gt;.&lt;a href=&quot;#2-Compose-a-ProfileContainer-with-a-HOC-that-contains-a-valid-IProfileService&quot; aria-label=&quot;2 Compose a ProfileContainer with a HOC that contains a valid IProfileService permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now we can create HOCs that use whatever kind of &lt;code class=&quot;language-text&quot;&gt;IProfileService&lt;/code&gt; we wish. It could be the one that connects to an API like what follows:&lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;hocs/withProfileService.tsx&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ProfileService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../services&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;withProfileServiceProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;withProfileService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;WrappedComponent&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HOC&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Component&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;withProfileServiceProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; profileService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ProfileService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; withProfileServiceProps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;profileService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProfileService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;WrappedComponent&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          &lt;span class=&quot;token attr-name&quot;&gt;profileService&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;profileService&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;          &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;HOC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; withProfileService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or it could be a mock one that uses an in-memory profile service as well.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;hocs/withMockProfileService.tsx&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; MockProfileService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../services&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;withProfileServiceProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;withProfileService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;WrappedComponent&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HOC&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Component&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;withProfileServiceProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; profileService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; MockProfileService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; withProfileServiceProps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;profileService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MockProfileService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;WrappedComponent&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          &lt;span class=&quot;token attr-name&quot;&gt;profileService&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;span class=&quot;token script-punctuation punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;profileService&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;          &lt;span class=&quot;token spread&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;HOC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; withProfileService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For our &lt;code class=&quot;language-text&quot;&gt;ProfileContainer&lt;/code&gt; to utilize the &lt;code class=&quot;language-text&quot;&gt;IProfileService&lt;/code&gt; from an HOC, it has to expect to receive an &lt;code class=&quot;language-text&quot;&gt;IProfileService&lt;/code&gt; as a prop within &lt;code class=&quot;language-text&quot;&gt;ProfileContainer&lt;/code&gt; rather than being added to the class as an attribute.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;containers/ProfileContainer.tsx&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IProfileService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./services&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IProfileData &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./models&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProfileContainerProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  profileService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IProfileService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProfileContainerState&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  profileData&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IProfileData &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProfileContainer&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Component&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
  ProfileContainerProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  ProfileContainerState
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ProfileContainerProps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      profileData&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;componentDidMount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; profileData&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IProfileData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;profileService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getProfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        profileData
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Ooops&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;Im a profile container&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, we can compose our &lt;code class=&quot;language-text&quot;&gt;ProfileContainer&lt;/code&gt; with whichever HOC we want- the one containing the real service, or the one containing the fake service for testing.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;tsx&quot;&gt;&lt;pre class=&quot;language-tsx&quot;&gt;&lt;code class=&quot;language-tsx&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; render &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react-dom&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; withProfileService &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./hocs/withProfileService&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; withMockProfileService &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./hocs/withMockProfileService&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ProfileContainer &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./containers/profileContainer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// The real service&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ProfileContainerWithService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;withProfileService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ProfileContainer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// The mock service&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ProfileContainerWithMockService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;withMockProfileService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ProfileContainer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Component&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; IState&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token plain-text&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ProfileContainerWithService&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;App&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[GraphQL's Greatest Architectural Advantages]]></title><description><![CDATA[Readers that frequent this blog know that I often look for answers to the hard questions in software design and architecture 🧐.  Over the…]]></description><link>https://khalilstemmler.com/articles/graphql/graphql-architectural-advantages/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/graphql/graphql-architectural-advantages/</guid><pubDate>Sat, 18 Jan 2020 22:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Readers that frequent this blog know that I often look for answers to the hard questions in software design and architecture 🧐. &lt;/p&gt;
&lt;p&gt;Over the past few years, we&apos;ve seen companies of all shapes and sizes like &lt;a href=&quot;https://www.apollographql.com/customers/expediagroup/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=graphql_architectural_advantages&quot;&gt;Expedia&lt;/a&gt;, &lt;a href=&quot;https://www.nerdwallet.com/blog/engineering/migrating-redux-graphql-nerdwallet-internship-experience/&quot;&gt;Nerdwallet&lt;/a&gt;, and &lt;a href=&quot;https://www.youtube.com/watch?utm_campaign=React%2BNewsletter&amp;#x26;utm_medium=email&amp;#x26;utm_source=React_Newsletter_189&amp;#x26;v=pywcFELoU8E&quot;&gt;AirBnb&lt;/a&gt; incrementally adopt GraphQL throughout their organizations. &lt;/p&gt;
&lt;p&gt;In this article, we&apos;ll discuss &lt;strong&gt;specific architectural advantages&lt;/strong&gt; to using GraphQL in your next project or adopting it for an existing one.&lt;/p&gt;
&lt;p&gt;We&apos;ll talk about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Where GraphQL belongs in the modern web application architecture.&lt;/li&gt;
&lt;li&gt;Why infrastructure code shouldn&apos;t be our focus on web development.&lt;/li&gt;
&lt;li&gt;The Data Graph: the newest layer in the modern web application stack.&lt;/li&gt;
&lt;li&gt;How the Data Graph unblocks frontend developers and removes the need for them to rely on backend developers.&lt;/li&gt;
&lt;li&gt;How to scale and separate concerns with Apollo Federation.&lt;/li&gt;
&lt;li&gt;How GraphQL and Apollo Federation eliminates the need to do API versioning.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;The-Hexagonal-architecture&quot; style=&quot;position:relative;&quot;&gt;The Hexagonal architecture&lt;a href=&quot;#The-Hexagonal-architecture&quot; aria-label=&quot;The Hexagonal architecture permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/TotherAlistair?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor&quot;&gt;Alistair Cockburn&lt;/a&gt;&apos;s &quot;Hexagonal architecture,&quot; says that the inner-most layer of our architecture holds the &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;application&lt;/a&gt; and &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/entities/&quot;&gt;domain layer&lt;/a&gt;. Right outside of that layer are the &lt;em&gt;adapters&lt;/em&gt; (or ports). &lt;/p&gt;
&lt;p&gt;Think of ports as &quot;a way to connect the outside world to the inside world.&quot; The outside world is full of technologies that we can use to build our application on top of. Outside, you&apos;ll find databases, external APIs, cloud services, and all kinds of other stuff. If we practice &lt;a href=&quot;https://khalilstemmler.com/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;dependency inversion&lt;/a&gt;, we can safely involve them within our application by defining &lt;em&gt;ports&lt;/em&gt;. Ports are abstractions. Contracts. They often appear in the form of &lt;strong&gt;interfaces&lt;/strong&gt; or &lt;strong&gt;abstract classes&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/architectural-advantages/hexagonal-architecture.svg&quot; alt=&quot;&amp;#x22;Hexagonal architecture&amp;#x22;&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Alistair Cockburn&apos;s &quot;Hexagonal Architecture&quot;.&lt;/p&gt;
&lt;p&gt;I believe pretty strongly in this type of architecture because it enables us to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Delay the decision on exactly which type of web server, database, transactional email provider, or caching technology until it&apos;s absolutely necessary to decide. We can always use an in-memory implementation of the &lt;em&gt;port&lt;/em&gt; for initial development efforts. &lt;/li&gt;
&lt;li&gt;It also prioritizes writing code that can be tested by using &lt;a href=&quot;/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;Dependency Injection&lt;/a&gt;. This helps to minimize &lt;a href=&quot;/wiki/concrete-class/&quot;&gt;concrete&lt;/a&gt; dependencies that can make code untestable.&lt;/li&gt;
&lt;li&gt;Lastly, it adjusts our focus to the application and domain-specific stuff. The stuff we can&apos;t just buy off the shelf or download. &lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Infrastructure-Components&quot; style=&quot;position:relative;&quot;&gt;Infrastructure Components&lt;a href=&quot;#Infrastructure-Components&quot; aria-label=&quot;Infrastructure Components permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;GraphQL servers and HTTP servers are examples of &lt;em&gt;infrastructure components&lt;/em&gt;.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Infrastructure components&lt;/b&gt;: Fundemental components that comprise the foundation of a web application. Based on the &lt;a href=&quot;/articles/software-design-architecture/organizing-app-logic/&quot;&gt;clean (or hexagonal) architecture&lt;/a&gt;, databases, web servers, and caches are &lt;i&gt;outer layer&lt;/i&gt; infrastructure components.&lt;/p&gt;
&lt;p&gt;We call infrastructural components &lt;em&gt;infrastructure&lt;/em&gt; because they are &lt;strong&gt;foundational to the application we build on top of it&lt;/strong&gt;. It&apos;s within this foundation- this skeleton, that we write our rich, domain-specific applications. The infrastructure is simply the driver.&lt;/p&gt;
&lt;p&gt;Another primary characteristic about infrastructure components is that they &lt;strong&gt;aren&apos;t the focus of our development efforts for a project&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Infrastructure components are tools trusted by the industry, and we only need to &lt;em&gt;configure&lt;/em&gt; them to make them work.&lt;/p&gt;
&lt;p&gt;Configuration of a GraphQL API involves:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Installing GraphQL&lt;/li&gt;
&lt;li&gt;Exposing a server endpoint&lt;/li&gt;
&lt;li&gt;Designing a schema&lt;/li&gt;
&lt;li&gt;Connecting resolvers to data sources&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This &lt;em&gt;is work&lt;/em&gt;, but it&apos;s not the &lt;strong&gt;focus&lt;/strong&gt; of our work on a project. &lt;/p&gt;
&lt;p&gt;If a certain piece of infrastructure technology is trusted by the industry, there&apos;s a good chance that we can expedite our development efforts by letting that tool do its job &lt;strong&gt;instead of developing our own infrastructure component&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Consider databases. They&apos;re &lt;em&gt;infrastructural&lt;/em&gt; too.&lt;/p&gt;
&lt;p&gt;For example, a &lt;strong&gt;Postgres database&lt;/strong&gt; is one of several databases we could use for a new project. Imagine the pushback you&apos;d get from your team if you tried to convince them it was essential for the project to write your own database from scratch. &lt;/p&gt;
&lt;p&gt;The scenario seems silly when we think about how it applies to choosing a persistence technology, but choosing your web application API style (transport/client-server technology) is a similar situation. &lt;/p&gt;
&lt;p&gt;It was last year (2019) when I realized that APIs cut deeper into the stack than we think. APIs touch the edges of our front-end frameworks&apos; &lt;em&gt;data stores&lt;/em&gt;, and they touch the &lt;em&gt;contracts&lt;/em&gt; (see &lt;a href=&quot;https://en.wikipedia.org/wiki/Design_by_contract&quot;&gt;Design by Contract&lt;/a&gt;) of our backend services. &lt;/p&gt;
&lt;p&gt;If this sounds a bit &lt;em&gt;virtual&lt;/em&gt;, that&apos;s because it kinda is. At Apollo GraphQL, we call that &lt;em&gt;virtual layer&lt;/em&gt; the &lt;em&gt;Data Graph&lt;/em&gt;. And Apollo builds tools that improves developer productivity working with it.&lt;/p&gt;
&lt;h2 id=&quot;The-Data-Graph&quot; style=&quot;position:relative;&quot;&gt;The Data Graph&lt;a href=&quot;#The-Data-Graph&quot; aria-label=&quot;The Data Graph permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I first heard the idea of a &lt;strong&gt;Data Graph&lt;/strong&gt; from &lt;a href=&quot;https://twitter.com/debergalis?lang=en&quot;&gt;Matt DeBergalis&lt;/a&gt;, CTO of &lt;a href=&quot;https://www.apollographql.com/docs/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=graphql_architectural_advantages&quot;&gt;Apollo GraphQL&lt;/a&gt;, at GraphQL Summit 2019.&lt;/p&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/EDqw-sGVq3k&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p class=&quot;caption&quot;&gt;I highly recommend Matt&apos;s talk at GraphQL Summit 2019 where he introduces the concept of the Data Graph.&lt;/p&gt;
&lt;p&gt;The Data Graph is &lt;em&gt;virtual layer&lt;/em&gt; that sits in between our client-side application and a GraphQL server. It holds &lt;strong&gt;the entirety of an organization&apos;s data and provides the language for how to fetch and mutate state within the entire organization&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Data Graph is &lt;em&gt;a declarative, self-documenting, organization-wide GraphQL API&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To me, the Data Graph is a previously &lt;strong&gt;missing layer&lt;/strong&gt; in the modern application stack.&lt;/p&gt;
&lt;img style=&quot;width: 100%;&quot; src=&quot;/img/blog/graphql/architectural-advantages/Virtual-Data-Graph.svg&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;Basic full stack Apollo Client + Server application stack.&lt;/p&gt;
&lt;h3 id=&quot;The-Data-Graph-brings-the-remote-state-closer-to-client-side-local-state&quot; style=&quot;position:relative;&quot;&gt;The Data Graph brings the remote state closer to client-side local state&lt;a href=&quot;#The-Data-Graph-brings-the-remote-state-closer-to-client-side-local-state&quot; aria-label=&quot;The Data Graph brings the remote state closer to client side local state permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;/wiki/3-common-goals-of-frontend-frameworks/&quot;&gt;Three challenges all front end frameworks&lt;/a&gt; need to solve are &lt;em&gt;data storage, change detection, and data flow&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;React developers typically need to patch on Redux or Context, and write lots of boilerplate code to satisfy these requirements. &lt;/p&gt;
&lt;p&gt;When Apollo released &lt;a href=&quot;https://www.apollographql.com/docs/react/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=graphql_architectural_advantages&quot;&gt;Apollo Client&lt;/a&gt; with &lt;a href=&quot;https://www.apollographql.com/docs/link/links/state/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=graphql_architectural_advantages&quot;&gt;apollo-link-state&lt;/a&gt;, they enabled React developers to meet &lt;em&gt;all three needs satisfied&lt;/em&gt; with a lot less code. &lt;/p&gt;
&lt;p&gt;Apollo-link-state (now baked directly into Apollo Client 2 and 3), made it possible for developers to write queries that address both remote state and local state at the exact same time. Remote state (sitting on a server) feels much &lt;em&gt;closer&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Take this query to fetch a particular dog by its breed, for example:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;queries/dog.js&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;const &lt;span class=&quot;token constant&quot;&gt;GET_DOG&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; gql`
  &lt;span class=&quot;token keyword&quot;&gt;query&lt;/span&gt; GetDogByBreed&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$breed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    dog&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;breed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$breed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      images &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        url
        id
        isLiked &lt;span class=&quot;token directive function&quot;&gt;@client&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# signal to resolve locally&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
`;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this query primarily intended to fetch remote resources, we can use the &lt;code class=&quot;language-text&quot;&gt;@client&lt;/code&gt; directive to refer to properties we want to fetch from our &lt;a href=&quot;https://www.apollographql.com/docs/react/data/local-state/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=graphql_architectural_advantages&quot;&gt;local cache&lt;/a&gt; based on a &lt;em&gt;client-side schema&lt;/em&gt;. Very cool that this can be done in the same request. Think about the amount of spread and &lt;code class=&quot;language-text&quot;&gt;Object.assign()&lt;/code&gt;s operations we normally do in a Redux environment.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.nerdwallet.com/assets/blog/wp-content/uploads/2019/08/GraphQL-Apollo-1400x821.png&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Depiction of the the simplified data-fetching architecture where the view is any front-end framework - Source &lt;a target=&quot;_bank&quot; href=&quot;https://www.nerdwallet.com/blog/engineering/migrating-redux-graphql-nerdwallet-internship-experience/&quot;&gt;nerdwallet&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Data Graph, with Apollo Server and Client on both ends of the connection, simplifies fetch logic, error logic, retry logic, pagination, caching, &lt;a href=&quot;https://www.apollographql.com/docs/react/performance/optimistic-ui/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=graphql_architectural_advantages&quot;&gt;optimistic UI&lt;/a&gt;, and various other types of boilerplate data-plumbing code.&lt;/p&gt;
&lt;img style=&quot;width: 100%;&quot; src=&quot;/img/blog/graphql/architectural-advantages/single-service-graph.svg&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;The Data Graph stretches from client to server and has an answer for the most common infrastructural problems when fetching data and mutating state in modern web applications.&lt;/p&gt;
&lt;p&gt;In order communicate with a backend service through GraphQL, &lt;a href=&quot;https://www.apollographql.com/docs/react/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=graphql_architectural_advantages&quot;&gt;Apollo Client&lt;/a&gt; exposes several client-side methods that, when invoked, converts the operation into the appropriate API to cross the Data Graph. &lt;/p&gt;
&lt;p&gt;On the &lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=graphql_architectural_advantages&quot;&gt;Apollo Server&lt;/a&gt; end, those API calls pass control off to &lt;a href=&quot;https://www.apollographql.com/docs/graphql-tools/resolvers/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=graphql_architectural_advantages&quot;&gt;resolvers&lt;/a&gt; responsible for fetching data using ORMs, raw SQL, caches, &lt;em&gt;other RESTful APIs&lt;/em&gt; or anything else you can think of. For mutations, a resolver can simply pass control to an application layer &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use case&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;By making the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt; the focal point of your application, switching from REST to GraphQL (or supporting both) is a breeze.&lt;/p&gt;
&lt;h3 id=&quot;GraphQL-is-self-documenting&quot; style=&quot;position:relative;&quot;&gt;GraphQL is self documenting&lt;a href=&quot;#GraphQL-is-self-documenting&quot; aria-label=&quot;GraphQL is self documenting permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;One bummer in mainting a RESTful API is keeping documentation up to date and adequate. &lt;/p&gt;
&lt;p&gt;There are two things that can change for a RESTful API.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The route + method combination&lt;/li&gt;
&lt;li&gt;The request shape + parameters&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A &lt;strong&gt;route + method combination&lt;/strong&gt; example is that it&apos;s quite easy for someone to move the operation that &lt;strong&gt;creates a user&lt;/strong&gt; from &lt;code class=&quot;language-text&quot;&gt;POST /users&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;POST /users/new&lt;/code&gt;. An API change like this would likely go unnoticed, break all clients of the API, and be virtually impossible for the API client to detect what the combination was changed to.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;request shape + parameters&lt;/strong&gt; example is one where the &lt;code class=&quot;language-text&quot;&gt;POST&lt;/code&gt; request to &lt;code class=&quot;language-text&quot;&gt;/users/new&lt;/code&gt; used to only require an &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt; and a &lt;code class=&quot;language-text&quot;&gt;password&lt;/code&gt;, but now, it requires a &lt;code class=&quot;language-text&quot;&gt;username&lt;/code&gt; property as well. The only way for an API client to understand what to do to remedy the request would be to check the error response (&lt;em&gt;hopefully, error messages are descriptive otherwise this too would be impossible&lt;/em&gt;).&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;If you consider &lt;a href=&quot;https://graphql.org/learn/introspection/&quot;&gt;introspection&lt;/a&gt; adequate documentation, then &lt;strong&gt;GraphQL is self-documenting&lt;/strong&gt; and &lt;em&gt;impossible&lt;/em&gt; for your API documentation to get &lt;em&gt;out&lt;/em&gt; of sync.&lt;/p&gt;
&lt;p&gt;Using &lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/testing/graphql-playground/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=graphql_architectural_advantages&quot;&gt;GraphQL Playground&lt;/a&gt;, one can browse all of the capabilities of a GraphQL endpoint.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/architectural-advantages/introspection.png&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;GraphQL Playground&apos;s GraphQL explorer can display all of the capabilities of a GraphQL endpoint due to the ability to execute introspection queries.&lt;/p&gt;
&lt;p&gt;In REST-land, I&apos;ve only seen APIs shipped with this amount of metadata built using Swagger. This is a very powerful feature that not only makes the code the single source of truth for documentation, but opens up the surface area of ways we can perform codegen to automate the creation of TypeScript types, client-side libraries, or service-to-service communication.&lt;/p&gt;
&lt;p&gt;Because the GraphQL language is ubiquitous and standardized, humans &lt;strong&gt;and machines&lt;/strong&gt; will have an easier time understanding how to integrate and work with it.&lt;/p&gt;
&lt;h2 id=&quot;Scaling-and-Separation-of-Concerns&quot; style=&quot;position:relative;&quot;&gt;Scaling and Separation of Concerns&lt;a href=&quot;#Scaling-and-Separation-of-Concerns&quot; aria-label=&quot;Scaling and Separation of Concerns permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://principledgraphql.com/integrity#1-one-graph&quot;&gt;Principled GraphQL&lt;/a&gt; states that,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Your company should have one unified graph, instead of multiple graphs created by each team.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The emergence of multiple graphs within a company is something that will start to happen as more and more teams catch on to GraphQL.&lt;/p&gt;
&lt;p&gt;Using &lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/federation/introduction/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=graphql_architectural_advantages&quot;&gt;Apollo Federation&lt;/a&gt;, each service team can build and manage their own GraphQL service from their bounded context, register it to an Apollo Gateway, distributing GraphQL operations across the entire enterprise.&lt;/p&gt;
&lt;img style=&quot;width: 100%;&quot; src=&quot;/img/blog/graphql/architectural-advantages/distributed-graph-features.svg&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;Apollo Federation lets us grow and expose a single Data Graph composed of several GraphQL endpoints.&lt;/p&gt;
&lt;p&gt;In Federation, you can &lt;em&gt;compose schemas&lt;/em&gt; and resolve fields from other services/bounded contexts. When a request comes in, those fields get resolved from the appropriate service 👍. &lt;/p&gt;
&lt;p&gt;Solving this problem is not uncommon for any organization of substantial size.&lt;/p&gt;
&lt;h3 id=&quot;A-single-endpoint&quot; style=&quot;position:relative;&quot;&gt;A single endpoint&lt;a href=&quot;#A-single-endpoint&quot; aria-label=&quot;A single endpoint permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;Open-Closed Principle&lt;/a&gt; from the SOLID principles states that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;A component/system/class should be open for extension, but closed for modification&quot;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Architecturally, because GraphQL only exposes a single endpoint to the client, it satisfies this principle. &lt;/p&gt;
&lt;p&gt;All of the complexities of how fields are being resolved are hidden from the client, and all it needs to focus on is how to build on top of the GraphQL server.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/architectural-advantages/data-graph-evolution.svg&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;An illustration that depicts the evolution of an organization&apos;s Data Graph over time.&lt;/p&gt;
&lt;h2 id=&quot;Empowers-frontend-developers&quot; style=&quot;position:relative;&quot;&gt;Empowers frontend developers&lt;a href=&quot;#Empowers-frontend-developers&quot; aria-label=&quot;Empowers frontend developers permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Data Graph reduces front-end developers&apos; reliance on backend developers to develop new endpoints for new use cases.&lt;/p&gt;
&lt;p&gt;Small UI changes where we rip out components or realize that we&apos;ve misjudged our data requirements and actually need a few more fields for components, happen quite often. Because this happens so often, and because REST is so rigid, it creates this dependency on the back-end team to make changes to the REST APIs any time we need adjustments.&lt;/p&gt;
&lt;p&gt;Depending on the team structure, each of the following questions signal potential to reduce developer productivity and create a reliance on the backend team.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is the team fragmented? Are front-end developers strictly front-end, or are they also allowed to work on the other side of the stack?&lt;/li&gt;
&lt;li&gt;Are your backend developers remote?&lt;/li&gt;
&lt;li&gt;Are your backend developers in the office?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;GraphQL-removes-the-need-to-manage-API-versions&quot; style=&quot;position:relative;&quot;&gt;GraphQL removes the need to manage API versions&lt;a href=&quot;#GraphQL-removes-the-need-to-manage-API-versions&quot; aria-label=&quot;GraphQL removes the need to manage API versions permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://principledgraphql.com/agility#5-use-an-agile-approach-to-schema-development&quot;&gt;Principled GraphQL&lt;/a&gt; also has a strong opinion on versioning. It states that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;The schema should be built incrementally based on actual requirements and evolve smoothly over time.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This means that the team should practice &lt;a href=&quot;https://principledgraphql.com/agility?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=graphql_architectural_advantages#5-use-an-agile-approach-to-schema-development&quot;&gt;agile schema development&lt;/a&gt; by iteratively making changes instead of chunking changes in huge releases.&lt;/p&gt;
&lt;p&gt;That&apos;s great, and all, but I live in the real world just like you. I know that that&apos;s not always possible, &lt;strong&gt;at least not without the proper tooling&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The Apollo platform has a feature called &lt;a href=&quot;https://engine.apollographql.com/login?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=graphql_architectural_advantages&quot;&gt;schema validation&lt;/a&gt; that lets you test every change against live production traffic and shows you when breaking changes are proposed, enabling teams to converse on how to continue.&lt;/p&gt;
&lt;p&gt;Neat!&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Getting started&lt;/b&gt;: For more information on how to use Schema Validation, check out &lt;a href=&quot;https://www.apollographql.com/docs/graph-manager/schema-validation/?utm_source=khalil&amp;utm_medium=article&amp;utm_campaign=graphql_architectural_advantages&quot;&gt;the docs&lt;/a&gt;, &lt;a href=&quot;https://blog.apollographql.com/move-fast-without-breaking-things-c7d3407ee8d6&quot;&gt;Evans Hauser&apos;s talk&lt;/a&gt;, and &lt;a href=&quot;https://engine.apollographql.com/login?utm_source=khalil&amp;utm_medium=article&amp;utm_campaign=graphql_architectural_advantages&quot;&gt;sign up for a free Teams trial&lt;/a&gt;.&lt;/p&gt;
&lt;!-- ## GraphQL schemas are Design by Contract

GraphQL schemas are strictly-typed contracts that do not care about the imperative (_how_ they get met), they only care that they are met.

If a schema containing a `mutation` to `createComment`

```graphql
{
  mutation CreateCommentMutation ($input: CreateCommentInput!){
    createComment(input: $input) {

    }
  }
}
```

- The schema of a GraphQL server is a strictly-typed contract that doesn&apos;t care about how it&apos;s met, it only cares that it is met. This is good for two reasons:
  - Strictly typed contract improves stability for client-side developers utilizing the endpoint.
  - It enables server-side developers to optimize code, change the internals as to how data is resolved, but forces the contract that they program to. 

- There are elegant ways to standarize and represent responses, errors, etc.

This is Barbara Liskov&apos;s &quot;[Liskov Subsitution Principle](/articles/solid-principles/solid-typescript/#LSP)&quot; which, put in simple terms by Uncle Bob, means that:

&gt; &quot;To build software systems from interchangeable parts, those parts must adhere to a contract that allows those parts to be substituted one for another.&quot;

If a GraphQL resolver takes in a `contentId: string` and returns either a `Post`, `Article`, or `PostNotFound`, `ArticleNotFound` type, that contract can be satisfied by a function or object that can determinately return one of those outputs for that input. --&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Within the modern web application architecture, GraphQL and RESTful Web Servers are infrastructure components. &lt;/li&gt;
&lt;li&gt;Infrastructure components are fundemental components that comprise the foundation of a domain-specific web application we code within them.&lt;/li&gt;
&lt;li&gt;Infrastructure components aren&apos;t the focus of most web development projects, so we should aim to spend most of our time on application and domain layer code.&lt;/li&gt;
&lt;li&gt;The Data Graph is a declarative, self-documenting, organization-wide GraphQL API, brings remote state closer to the client-side, and can be scaled using &lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/federation/introduction/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=graphql_architectural_advantages&quot;&gt;Apollo Federation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Front-end developers are empowered to create their own data-fetching use cases without the reliance on backend developers by using the Data Graph.&lt;/li&gt;
&lt;li&gt;GraphQL removes the need to manage API versions and Apollo&apos;s &lt;a href=&quot;https://www.apollographql.com/docs/graph-manager/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=graphql_architectural_advantages&quot;&gt;Graph Manager&lt;/a&gt; can faciliate production schema validation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are a lot of scenarios where GraphQL makes sense architecturally.&lt;/p&gt;
&lt;p&gt;I&apos;m still in the process of trying everything out for myself. I&apos;ll be updating this article periodically as I get my hands dirty, so check back in a little while.&lt;/p&gt;
&lt;!-- - Talking point: REST requires documentation to accompany it. With GraphQL, the code _is_ the documentation.
 - Supporting point: Introspection --&gt;
&lt;!-- - Talking point: You can still do service-to-service communication, and there are some valuable use cases, like needing to 
 - Supporting: Service-to-service communication using GraphQL is still advantageous due to introspection, but this is often turned off in production. --&gt;
&lt;!-- - Talking point: The greatest architectural advantage for server-side developers is there is a single contract to maintain, and it reduces risk. 
 - Supporting point: The entire contract for the way data goes in, and data comes out of your enterprise can be defined in a single schema, even if you&apos;re running a distributed microservice architecture. --&gt;
&lt;!-- - Talking point: GraphQL can be incrementally adopted, which means that you can run GraphQL and REST simultaneously. --&gt;</content:encoded></item><item><title><![CDATA[No title]]></title><description><![CDATA[Every frontend framework has their own opinionated way to solve the same three problems. 1. Data storage Defining the shape, changing, and…]]></description><link>https://khalilstemmler.com/wiki/3-common-goals-of-frontend-frameworks/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/3-common-goals-of-frontend-frameworks/</guid><pubDate>Wed, 08 Jan 2020 04:05:26 GMT</pubDate><content:encoded>&lt;p&gt;Every frontend framework has their own opinionated way to solve the same three problems.&lt;/p&gt;
&lt;h2 id=&quot;1-Data-storage&quot; style=&quot;position:relative;&quot;&gt;1. Data storage&lt;a href=&quot;#1-Data-storage&quot; aria-label=&quot;1 Data storage permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Defining the shape, changing, and accessing data from the store&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;Apollo-Client--React-Hooks&quot; style=&quot;position:relative;&quot;&gt;Apollo Client + React Hooks&lt;a href=&quot;#Apollo-Client--React-Hooks&quot; aria-label=&quot;Apollo Client  React Hooks permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Using &lt;a href=&quot;https://www.apollographql.com/docs/react/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=three_frontend_goals&quot;&gt;Apollo Client&lt;/a&gt; we can create a store to represent the &lt;strong&gt;local state&lt;/strong&gt; as a client-side cache, fundamentally replacing the need to use Redux to maintain a client-side store.&lt;/p&gt;
&lt;p&gt;Queries/mutations that need &lt;strong&gt;remote state&lt;/strong&gt; can also be written in combination with remote fields to handle use cases where we add flags or booleans to data for local presentation. &lt;/p&gt;
&lt;p class=&quot;filename&quot;&gt;queries/dog.js&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;const &lt;span class=&quot;token constant&quot;&gt;GET_DOG&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; gql`
  &lt;span class=&quot;token keyword&quot;&gt;query&lt;/span&gt; GetDogByBreed&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$breed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    dog&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;breed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$breed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      images &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        url
        id
        isLiked &lt;span class=&quot;token directive function&quot;&gt;@client&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# signal to resolve locally&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
`;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It&apos;s pretty nifty.&lt;/p&gt;
&lt;p&gt;Anything data not found in the client-side cache is fetched remotely and cached on its way in.&lt;/p&gt;
&lt;h2 id=&quot;2-Change-detection&quot; style=&quot;position:relative;&quot;&gt;2. Change detection&lt;a href=&quot;#2-Change-detection&quot; aria-label=&quot;2 Change detection permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Signaling to components that data has changed&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;3-Data-flow&quot; style=&quot;position:relative;&quot;&gt;3. Data flow&lt;a href=&quot;#3-Data-flow&quot; aria-label=&quot;3 Data flow permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;The direction that changes flow and responding to change&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[Decade in Review | 2010-2020]]></title><description><![CDATA[At the time of writing this, I've been on Earth for about ~2.4 decades. That means that ten years ago, I was the very tender age of fourteen…]]></description><link>https://khalilstemmler.com/blogs/life/decade-in-review/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/life/decade-in-review/</guid><pubDate>Thu, 02 Jan 2020 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;At the time of writing this, I&apos;ve been on Earth for about ~2.4 decades. That means that ten years ago, I was the very tender age of fourteen. Remember fourteen? Remember all that confusion, boredom, and frustration (and maybe also rebellion)?&lt;/p&gt;
&lt;p&gt;At fourteen, everything seems possible. Our dreams of becoming a rockstar, playing sold-out shows, traveling the world, and other big and grandiose things don&apos;t seem all that ridiculous. At fourteen, everyone&apos;s got their own &lt;em&gt;time blanket&lt;/em&gt; to cover their eyes with to stay hidden from the real-world boogeyman: &lt;em&gt;reality&lt;/em&gt;. Usually, at fourteen, we don&apos;t have to make any of those big decisions just &lt;em&gt;yet&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Flash forward ten years, and I&apos;m twenty-four. &lt;/p&gt;
&lt;p&gt;I&apos;ve made all the &lt;strong&gt;most significant decisions of my life so far&lt;/strong&gt; including what I want to do for a living, who I want to spend my time with, where I want to live, and what I want to achieve in the next decade.&lt;/p&gt;
&lt;p&gt;In ten years, I have to say that I&apos;m really proud of how far I&apos;ve come. &lt;/p&gt;
&lt;p&gt;I&apos;ve gone from high school to working in a factory, to running my own lawn care business, graduating from college and university, learning various instruments, recording 7 full-length albums, playing shows, working tech jobs, building a startup, creating products and blogging, and eventually landing my dream job.&lt;/p&gt;
&lt;p&gt;In this post, I&apos;d like to recollect some of the most profound, weird, and memorable moments over the last decade.&lt;/p&gt;
&lt;h2 id=&quot;2010&quot; style=&quot;position:relative;&quot;&gt;2010&lt;a href=&quot;#2010&quot; aria-label=&quot;2010 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;I-laughed-almost-every-day-of-high-school&quot; style=&quot;position:relative;&quot;&gt;I laughed almost every day of high school&lt;a href=&quot;#I-laughed-almost-every-day-of-high-school&quot; aria-label=&quot;I laughed almost every day of high school permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Every single day of high school in Brantford, Ontario felt like it was the funniest day on Earth. Surrounded by cartoon characters, I met hilarious people like James, a weed-smoking compulsive that thought he needed to buy the friendship of his peers with chocolate bars stolen from his dad&apos;s convenience store. I also met people like Phil, a lanky stoner influenced by Marilyn Manson, who often attended class with a white contact in one eye. Hilarious.&lt;/p&gt;
&lt;p&gt;I can barely remember a moment I wasn&apos;t laughing (&lt;em&gt;and I probably bought myself several additional years of life with all of that laughter&lt;/em&gt;).&lt;/p&gt;
&lt;h3 id=&quot;Favourite-artists&quot; style=&quot;position:relative;&quot;&gt;Favourite artists&lt;a href=&quot;#Favourite-artists&quot; aria-label=&quot;Favourite artists permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Green Day (I could play all of their songs on drums; my favorite album was &lt;em&gt;Insomniac&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Blink-182 (what? they were &lt;em&gt;good&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Weezer (&lt;em&gt;Pinkerton&lt;/em&gt; was the emo jam back then)&lt;/li&gt;
&lt;li&gt;AFI (I still bop their first few punk records)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2011&quot; style=&quot;position:relative;&quot;&gt;2011&lt;a href=&quot;#2011&quot; aria-label=&quot;2011 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;I-discovered-my-love-for-programming-in-Grade-11-Computer-Science&quot; style=&quot;position:relative;&quot;&gt;I discovered my love for programming in Grade 11 Computer Science&lt;a href=&quot;#I-discovered-my-love-for-programming-in-Grade-11-Computer-Science&quot; aria-label=&quot;I discovered my love for programming in Grade 11 Computer Science permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Formerly a math teacher, Mr. Levac was suddenly tasked with teaching high school students the fundamentals of Computer Science. &lt;/p&gt;
&lt;p&gt;Having gone to university for programming later, I thought he did a fantastic job. We learned about searching, sorting, arrays, hashtables, and all the basics of programming with Java. By the end of the class, I had programmed a two-player game of chess.&lt;/p&gt;
&lt;p&gt;I was very fortunate to have the opportunity to take a programming class in high school.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This class was the time I ever experienced that &lt;strong&gt;empty mind&lt;/strong&gt; feeling you get when you get into the &lt;em&gt;flow&lt;/em&gt; of programming. I always felt the class was short, and that&apos;s likely because I was having so much fun with it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;I-learned-the-value-of-backing-up-files-in-multiple-places-when-I-lost-an-album-I-worked-an-entire-summer-on-recording&quot; style=&quot;position:relative;&quot;&gt;I learned the value of backing up files in multiple places when I lost an album I worked an entire summer on recording&lt;a href=&quot;#I-learned-the-value-of-backing-up-files-in-multiple-places-when-I-lost-an-album-I-worked-an-entire-summer-on-recording&quot; aria-label=&quot;I learned the value of backing up files in multiple places when I lost an album I worked an entire summer on recording permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I spent an entire summer in my parents&apos; basement working on a punk album using a crappy little Dell netbook, Audacity, and FL Studio. &lt;/p&gt;
&lt;p&gt;After completing the record and rendering it all out to WAV and MP3s, I was devastated when my hard drive with all of the original project files on it- died.&lt;/p&gt;
&lt;p&gt;Hard lesson learned that year.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If it doesn&apos;t exist in at least two places, it doesn&apos;t exist at all.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I still have the final exported audio files, but listening to the way it was mixed back then makes me cringe. If only I could go back in time...&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; src=&quot;/img/blog/thoughts/decade-in-review/2012-setup.png&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;This is what my setup looked like at the start of this decade.&lt;/p&gt;
&lt;h3 id=&quot;Favourite-artists-1&quot; style=&quot;position:relative;&quot;&gt;Favourite artists&lt;a href=&quot;#Favourite-artists-1&quot; aria-label=&quot;Favourite artists 1 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Nine Inch Nails&lt;/li&gt;
&lt;li&gt;Queens of the Stone Age&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2012&quot; style=&quot;position:relative;&quot;&gt;2012&lt;a href=&quot;#2012&quot; aria-label=&quot;2012 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;My-parents-wanted-me-to-be-a-lawyer-so-I-did-a-co-op-to-test-it-out&quot; style=&quot;position:relative;&quot;&gt;My parents wanted me to be a lawyer, so I did a co-op to test it out&lt;a href=&quot;#My-parents-wanted-me-to-be-a-lawyer-so-I-did-a-co-op-to-test-it-out&quot; aria-label=&quot;My parents wanted me to be a lawyer so I did a co op to test it out permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In Ontario, we have to take a Careers class and complete a test that tells you what job you&apos;d be well suited for. I seriously think we need to re-evaluate how those tests work because mine spit out that I should become a &lt;em&gt;Bereavement Counselor&lt;/em&gt; 🙃. Hmm.&lt;/p&gt;
&lt;p&gt;Anyway, even though I liked computers and coding, my parents really wanted me to try to get into law. After all, what parent doesn&apos;t want their kid to be a lawyer?&lt;/p&gt;
&lt;p&gt;I figured &lt;em&gt;why not&lt;/em&gt;, let&apos;s treat it as an experience, right? I&apos;m so glad I found a co-op placement at the Brantford Superior Court of Justice through my school. &lt;strong&gt;Within two days, I realized how much it wasn&apos;t for me&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Periodically in between doing really boring filing work, I got time to sit in on custody battles, people in trouble for shoplifting, vandalism, theft, and all kinds of other creatively heinous crimes, but it totally wasn&apos;t the kind of thing I wanted to spend my time thinking about.&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; src=&quot;/img/blog/thoughts/decade-in-review/superior-court-of-justice.png&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;A young Khalil working at the Superior Court of Justice in Brantford with endless boxes of pages to find and replace in books.&lt;/p&gt;
&lt;p&gt;Even though it was 4 months of boredom and the thing I enjoyed the most was helping troubleshoot intranet issues, I appreciated the experience because now I know for sure.&lt;/p&gt;
&lt;h3 id=&quot;Favourite-artists-2&quot; style=&quot;position:relative;&quot;&gt;Favourite artists&lt;a href=&quot;#Favourite-artists-2&quot; aria-label=&quot;Favourite artists 2 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Not going to tell you because it&apos;s embarrassing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2013&quot; style=&quot;position:relative;&quot;&gt;2013&lt;a href=&quot;#2013&quot; aria-label=&quot;2013 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;I-lost-a-20000-scholarship-and-couldnt-find-a-part-time-job-so-I-worked-in-a-factory&quot; style=&quot;position:relative;&quot;&gt;I lost a $20,000 scholarship and couldn&apos;t find a part-time job, so I worked in a factory&lt;a href=&quot;#I-lost-a-20000-scholarship-and-couldnt-find-a-part-time-job-so-I-worked-in-a-factory&quot; aria-label=&quot;I lost a 20000 scholarship and couldnt find a part time job so I worked in a factory permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I think the &lt;a href=&quot;https://www.schulichleaders.com/&quot;&gt;Schulich Scholarship&lt;/a&gt; is actually Canada&apos;s biggest scholarship (today, it&apos;s $100k CAD for STEM students). I was nominated for it!&lt;/p&gt;
&lt;p&gt;It came down to two other students and me. Unfortunately, I didn&apos;t win it. Unfortunately for the person who won it, they ended up dropping out of school and giving back all the money after the first year to go into trades instead. Nonetheless, I figured things out and was able to fund my way into Brock University/Sheridan College&apos;s &lt;em&gt;Computing and Internet Telecommunications Program&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Because Brantford&apos;s part-time job economy for high school students was pretty poor, the only job I was able to find was working as a temp in a soap factory.&lt;/p&gt;
&lt;p&gt;That sucked. It felt like I barely saw daylight for months. Though I did get some pretty hilarious stories from it. &lt;/p&gt;
&lt;h3 id=&quot;Started-school-at-Brock-University-and-met-some-of-my-best-friends-to-this-day&quot; style=&quot;position:relative;&quot;&gt;Started school at Brock University and met some of my best friends to this day&lt;a href=&quot;#Started-school-at-Brock-University-and-met-some-of-my-best-friends-to-this-day&quot; aria-label=&quot;Started school at Brock University and met some of my best friends to this day permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The main difference I&apos;ve noticed between college and university is that in college, you end up doing a lot of &lt;em&gt;busy work&lt;/em&gt;, but in university, the assignments that you get can take anywhere from an hour to 2 weeks to complete.&lt;/p&gt;
&lt;p&gt;For example, in Mathematical Reasoning, we&apos;d often get these single page assignments with one or two formulas to solve. I noticed that we ended up spending more time just trying to &lt;em&gt;understand the problem&lt;/em&gt; than we did actually solving the problem.&lt;/p&gt;
&lt;p&gt;And when I got to college, it was just &lt;em&gt;a lot of work&lt;/em&gt;- not as theoretically challenging, but man I always had something keeping me busy.&lt;/p&gt;
&lt;p&gt;That first week at Brock, getting my ass kicked in the Mathematical Reasoning class, I went to the math lab, rallied up a group of first years also struggling, and worked through those problems together. Several of those first years have become really good friends to me that I still keep in contact with to this day.&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; src=&quot;/img/blog/thoughts/decade-in-review/2013-recording.JPG&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;Working on Axion EP in my dorm.&lt;/p&gt;
&lt;h3 id=&quot;Stuff-I-made&quot; style=&quot;position:relative;&quot;&gt;Stuff I made&lt;a href=&quot;#Stuff-I-made&quot; aria-label=&quot;Stuff I made permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Before I left for university, me and two buddies recorded &lt;a href=&quot;https://cyanidecanaries.bandcamp.com/album/the-sandpaper-disco-ll&quot;&gt;The Sandpaper Disco II&lt;/a&gt;, an electronic/dance album with a &lt;em&gt;few&lt;/em&gt; good songs :p&lt;/li&gt;
&lt;li&gt;In the Winter, I recorded &lt;a href=&quot;https://cyanidecanaries.bandcamp.com/album/axion-ep&quot;&gt;Axion EP&lt;/a&gt; in my dorm room, a downtempo trip-hop/electronic record under the pseudonym of Cyanide Canaries.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Favourite-artists-3&quot; style=&quot;position:relative;&quot;&gt;Favourite artists&lt;a href=&quot;#Favourite-artists-3&quot; aria-label=&quot;Favourite artists 3 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Massive Attack&lt;/li&gt;
&lt;li&gt;Dead Kennedys&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2014&quot; style=&quot;position:relative;&quot;&gt;2014&lt;a href=&quot;#2014&quot; aria-label=&quot;2014 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;I-wrote-my-first-piece-of-distributable-software-a-glitch-art-program&quot; style=&quot;position:relative;&quot;&gt;I wrote my first piece of distributable software: a glitch art program&lt;a href=&quot;#I-wrote-my-first-piece-of-distributable-software-a-glitch-art-program&quot; aria-label=&quot;I wrote my first piece of distributable software a glitch art program permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After taking &lt;a href=&quot;https://www.cosc.brocku.ca/about_cosc1p02&quot;&gt;COSC 1P02&lt;/a&gt; and learning about basic data structures like Queues and Stacks, I was feeling like I learned some really cool stuff but wasn&apos;t sure how to apply it in the real world just yet.&lt;/p&gt;
&lt;p&gt;I had this idea for a really long time that I wanted to figure out how to build my own &lt;em&gt;glitch art program&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Glitch art is exactly what it sounds like. You take an image, mess it up by changing some of its digital representation, save it back, and then look at it.&lt;/p&gt;
&lt;p&gt;It wasn&apos;t until second-year&apos; s&lt;a href=&quot;https://www.cosc.brocku.ca/offerings/cosc2p03&quot;&gt;COSC 2P03 - Advanced Data Structures&lt;/a&gt; that things finally clicked.&lt;/p&gt;
&lt;p&gt;I remember staying up all night at my friend Kirk&apos;s house, getting the code on &lt;a href=&quot;https://github.com/stemmlerjs/glitchie&quot;&gt;Glitchie&lt;/a&gt; to work.&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; src=&quot;https://cloud.githubusercontent.com/assets/6892666/13548037/f228d03c-e2b3-11e5-962c-be4a2074a9bd.gif&quot;&gt;
&lt;p class=&quot;caption&quot;&gt;The first program I ever built (that I was proud of).&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;You can download the jar and try it out &lt;a href=&quot;https://github.com/stemmlerjs/glitchie&quot;&gt;on Github&lt;/a&gt;. I haven&apos;t tested it on Mac yet.&lt;/p&gt;
&lt;h3 id=&quot;Ran-a-lawn-care-business-in-order-to-raise-more-funds-to-pay-for-my-next-years-of-university&quot; style=&quot;position:relative;&quot;&gt;Ran a lawn-care business in order to raise more funds to pay for my next years of university&lt;a href=&quot;#Ran-a-lawn-care-business-in-order-to-raise-more-funds-to-pay-for-my-next-years-of-university&quot; aria-label=&quot;Ran a lawn care business in order to raise more funds to pay for my next years of university permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the summer, I needed to raise some more money to head back for the second year of school.&lt;/p&gt;
&lt;p&gt;I was really fed up with factory work, so I came up with the idea of running my own lawn-care business with my stepdad. We called it &quot;Steps Lawn Care.&quot;&lt;/p&gt;
&lt;p&gt;Honestly, we made a killing. &lt;/p&gt;
&lt;p&gt;Since my stepdad had his own full-time job, he would only help me out in the evenings, so throughout the day, I would drive the truck with the trailer across Brantford, Paris, Hamilton cutting and rolling lawns. I was able to pull in $300-600 a day on average if it wasn&apos;t too hot outside.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Tip&lt;/b&gt;: You want to get up really early and get the big lawns out of the way when you&apos;ve still got a little bit of that early morning chill goin&apos; on. Pushing a lawnmower in 25-degree heat is straight-up death 💀.&lt;/p&gt;
&lt;h3 id=&quot;Stuff-I-made-1&quot; style=&quot;position:relative;&quot;&gt;Stuff I made&lt;a href=&quot;#Stuff-I-made-1&quot; aria-label=&quot;Stuff I made 1 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Really influenced by the trip-hop genre and artists like Massive Attack, Tricky, and Portishead, I recorded this &lt;em&gt;warm&lt;/em&gt; trip-hop + surf-rock album called &lt;a href=&quot;https://cyanidecanaries.bandcamp.com/album/separation-stories&quot;&gt;Separation Stories&lt;/a&gt; in between classes. My process was to record an entire surf-rock song, cut the guitar riffs up into little samples, slow &apos;em down, and then organize them into a downtempo track using a &lt;a href=&quot;https://www.ableton.com/en/products/controllers/launchpad/&quot;&gt;Novation Launchpad&lt;/a&gt;. I would record vocals, more guitars, and place other embellishments over the track in FL Studio.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Favourite-artists-4&quot; style=&quot;position:relative;&quot;&gt;Favourite artists&lt;a href=&quot;#Favourite-artists-4&quot; aria-label=&quot;Favourite artists 4 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The Clash&lt;/li&gt;
&lt;li&gt;Beastie Boys&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2015&quot; style=&quot;position:relative;&quot;&gt;2015&lt;a href=&quot;#2015&quot; aria-label=&quot;2015 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Moved-to-Ottawa-and-worked-at-IBM&quot; style=&quot;position:relative;&quot;&gt;Moved to Ottawa and worked at IBM&lt;a href=&quot;#Moved-to-Ottawa-and-worked-at-IBM&quot; aria-label=&quot;Moved to Ottawa and worked at IBM permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;My first co-op job through school was at IBM in Ottawa. &lt;/p&gt;
&lt;p&gt;It was one of the longest and coldest Winters I&apos;ve ever experienced. It felt like I was living in an extended version of The Girl With The Dragon Tattoo (the Daniel Craig one).&lt;/p&gt;
&lt;p&gt;I was a Technical Analyst at IBM and accompanied by two of my brock buds, Imran and Sulman. Lots of fun times being thrown into the deep end, resolving customer service requests on technologies that we practically knew nothing about. To this day, I still can&apos;t tell you what a &lt;em&gt;star schema&lt;/em&gt; is.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Quip of the decade&lt;/b&gt;: Once, I forgot to pack a lunch and decided that I would just spend my lunch break reading my copy of Kim Gordon&apos;s autobiography that I brought from home. I entered the elevevator with Sulman, Imran, and our team lead, Cam. Cam asked me where my lunch was, and I told him I forgot it. A couple seconds of silence passed. Before the doors to the elevator opened, Sulman murmured the words, &quot;Readers digest&quot;. Two more seconds passed. Then, we all bursted out with uncontrollable laughter.&lt;/p&gt;
&lt;h3 id=&quot;Freak-punk-shows&quot; style=&quot;position:relative;&quot;&gt;Freak punk shows&lt;a href=&quot;#Freak-punk-shows&quot; aria-label=&quot;Freak punk shows permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Ottawa and Montreal have thriving art scenes. One particular night after work, I walked across town in the blistering cold looking The Gabba Hey, an underground punk venue located in an industrial district of Ottawa.&lt;/p&gt;
&lt;p&gt;Upon walking in, noticing punks decked out in studs, leather, and spandex, I was sure that I was going to be the only one attending this show in a full suit and tie getup. While that was &lt;em&gt;technically correct&lt;/em&gt;, it was the &lt;em&gt;virtual presence&lt;/em&gt; of Mr. Node and his cut-up nine-to-five suit and tie uniform that also occupied the space.&lt;/p&gt;
&lt;p&gt;Pretention aside, before any bands played that night, we were shown a documentary about a Montreal freak punk band called &lt;em&gt;Thee Nodes&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Mr. Node was a mental mummy businessman that performed with toilet paper wrapped around his head and had about as much to say as &lt;a href=&quot;https://en.wikipedia.org/wiki/Jello_Biafra&quot;&gt;Jello Biafra&lt;/a&gt;, although in a less witty and cutting way.&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; src=&quot;/img/blog/thoughts/decade-in-review/thee-nodes.jpg&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;Mr. Node himself alongside Marc The Narc performing at a house show. You can feel the heat and congestion from just looking at this photograph.&lt;/p&gt;
&lt;p&gt;I don&apos;t know. Something happened here witnessing this. I&apos;ve never seen music performed so passionately. It was probably more &lt;em&gt;performance art&lt;/em&gt; than music. Art had been so important to me for such a long time, and on that day, something shifted in my head. I&apos;m not sure how to explain it. Weird that I&apos;d even mention it on a decade retrospective, but it&apos;s unexplainably important to me for some reason.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Further reading&lt;/b&gt;: I find these guys fascinating. If you&apos;re interested, check out this Vice article titled &quot;&lt;a href=&quot;https://www.vice.com/en_au/article/6a9m86/thee-nodes-went-to-the-future-and-came-back-insane&quot;&gt;Thee Nodes Went to the Future and Came Back Insane&lt;/a&gt;&quot;. If you&apos;re still intrigued, I just learned that the original documentary &quot;&lt;a href=&quot;https://www.youtube.com/watch?v=_T6Ti2S_fLY&quot;&gt;Who Are You Mr. Node?&lt;/a&gt;&quot; is finally on YouTube.&lt;/p&gt;
&lt;h3 id=&quot;Started-learning-computer-networking-at-Sheridan-College-in-Oakville&quot; style=&quot;position:relative;&quot;&gt;Started learning computer networking at Sheridan College in Oakville&lt;a href=&quot;#Started-learning-computer-networking-at-Sheridan-College-in-Oakville&quot; aria-label=&quot;Started learning computer networking at Sheridan College in Oakville permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The university program I chose was half computer science and programming, and half computer networking.&lt;/p&gt;
&lt;p&gt;These first few weeks were kind of rough because I was joining a second-semester class that had already learned all the basics and were getting ready to apply real-world networking protocols like OSPF, RIP, MLPS, and IS-IS. &lt;/p&gt;
&lt;p&gt;I got a couple of books off someone, busted my ass that first month, and somehow caught up. Because I&apos;m more interested in programming and software design, I almost never need to utilize any of the core internet routing and networking knowledge I acquired at school, but I at least have an appreciation for just how complex the internet really is.&lt;/p&gt;
&lt;h3 id=&quot;Did-my-first-software-development-co-op-and-learned-the-hard-way-how-important-it-is-to-test-your-code&quot; style=&quot;position:relative;&quot;&gt;Did my first software development co-op and learned the hard way how important it is to test your code&lt;a href=&quot;#Did-my-first-software-development-co-op-and-learned-the-hard-way-how-important-it-is-to-test-your-code&quot; aria-label=&quot;Did my first software development co op and learned the hard way how important it is to test your code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;My first actual software development job was as a Java Developer at a company in Cambridge that builds ERP Software.&lt;/p&gt;
&lt;p&gt;The codebase was &lt;em&gt;very bad&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;My first assignment was to &quot;take some SQL code, put it in this block of Java code, and run it.&quot; I was also told that I&apos;d &quot;know if it works if it doesn&apos;t return any rows.&quot;&lt;/p&gt;
&lt;p&gt;Weird stuff.&lt;/p&gt;
&lt;p&gt;The hardest lesson I ever learned was that I should never skip out on running tests and making sure my code works because once, I neglected to spend time doing any testing, and the code went out to the client completely busted. I was called in to speak to the manager that comes up with the requirements and given an incredibly stern and upsetting talking to.&lt;/p&gt;
&lt;p&gt;Though there might have been a better way to go about doing that, I saw it from his point of view. Test your code, kids.&lt;/p&gt;
&lt;h3 id=&quot;Stuff-I-made-2&quot; style=&quot;position:relative;&quot;&gt;Stuff I made&lt;a href=&quot;#Stuff-I-made-2&quot; aria-label=&quot;Stuff I made 2 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;At this time, I was mostly into noise rock and recorded an album called &quot;&lt;a href=&quot;https://cyanidecanaries.bandcamp.com/album/death-to-the-police-force&quot;&gt;Death to the Police Force&lt;/a&gt;.&quot; One of my better-sounding releases.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Favourite-artists-5&quot; style=&quot;position:relative;&quot;&gt;Favourite artists&lt;a href=&quot;#Favourite-artists-5&quot; aria-label=&quot;Favourite artists 5 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Sonic Youth&lt;/li&gt;
&lt;li&gt;Black Flag&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2016&quot; style=&quot;position:relative;&quot;&gt;2016&lt;a href=&quot;#2016&quot; aria-label=&quot;2016 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Started-working-on-Univjobs&quot; style=&quot;position:relative;&quot;&gt;Started working on Univjobs&lt;a href=&quot;#Started-working-on-Univjobs&quot; aria-label=&quot;Started working on Univjobs permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Back at Sheridan, I was introduced to a fellow named Charles, who was as interested in programming and entrepreneurship as I was. Charles met with the mayor of Mississauga and asked her what the biggest problems in Mississauga were. She said that the single biggest problem was &lt;em&gt;brain leak&lt;/em&gt;, meaning that all of the smart STEM students were leaving Mississauga to find tech jobs in Toronto while there are plenty of opportunities in Mississauga that no one knew about.&lt;/p&gt;
&lt;p&gt;Charles asked me to help him with his database schema and later asked me to help him develop the platform. Seeing how passionate he was about solving the problem, I decided to invest my time to work with him on what would become Univjobs.&lt;/p&gt;
&lt;p&gt;The application was built using React.js, Redux, Node, and eventually refactored to TypeScript and deployed on AWS.&lt;/p&gt;
&lt;h3 id=&quot;Regularly-had-nightmares-about-my-computer-networking-professor&quot; style=&quot;position:relative;&quot;&gt;Regularly had nightmares about my computer networking professor&lt;a href=&quot;#Regularly-had-nightmares-about-my-computer-networking-professor&quot; aria-label=&quot;Regularly had nightmares about my computer networking professor permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Bill Farkas is well-known for being one of the hardest professors you&apos;ll ever have. He created the Internet Telecommunications program in the 90s, took a bet on TCP/IP, and will most certainly make you learn. You will not graduate if he doesn&apos;t feel like you put in the effort. &lt;/p&gt;
&lt;p&gt;The way I feel about it now is kind of the way that you feel about parents that were hard on you growing up- you know they were hard on you for your own good, but man, it really sucked.&lt;/p&gt;
&lt;p&gt;Bill expected students to put in 60-70 hours per week and come prepared for lectures and seminars. I used to spend 15-20 hour days in the computer networking lab and often slept there in order to attend the class the next day. Unfortunately, that was the norm at the time. Any social life or balance I had before attending Bill&apos;s classes were completely killed by the time I started.&lt;/p&gt;
&lt;p&gt;For me, the most positive outcome I got from taking Bill&apos;s classes was my improved ability to present technical information in a concise and approachable manner. &lt;/p&gt;
&lt;p&gt;Bill would often draw out a network topology, cut a few lines, and then ask someone to come up and explain to the class how the network will converge. &lt;/p&gt;
&lt;p&gt;The challenge is: if you provide any &lt;em&gt;superfluous&lt;/em&gt; information, Bill will &lt;strong&gt;roast you in front of the class&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;If you don&apos;t provide enough information, Bill &lt;strong&gt;will roast you in front of the class&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;If you provide incorrect information, Bill &lt;strong&gt;will roast you in front of the class&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;In fact, you have to work really hard to &lt;em&gt;not&lt;/em&gt; get &lt;strong&gt;roasted in front of the class&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;Either that or just accept the fact that &lt;strong&gt;you will get roasted in front of the class&lt;/strong&gt;. Talk about facing your fears of public speaking. &lt;/p&gt;
&lt;p&gt;A very valuable experience that did a lot more good than bad, though some couldn&apos;t take it, which made the graduating class pretty small.&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; src=&quot;/img/blog/thoughts/decade-in-review/2016-me.JPG&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;A goofy-looking Khalil in 2016.&lt;/p&gt;
&lt;h3 id=&quot;Stuff-I-made-3&quot; style=&quot;position:relative;&quot;&gt;Stuff I made&lt;a href=&quot;#Stuff-I-made-3&quot; aria-label=&quot;Stuff I made 3 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;My tastes had shifted more towards post-punk and popular music by this time. I recorded &quot;&lt;a href=&quot;https://cyanidecanaries.bandcamp.com/album/dig-it-up&quot;&gt;Dig It Up&lt;/a&gt;,&quot; probably my most accessible music to date.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Favourite-artists-6&quot; style=&quot;position:relative;&quot;&gt;Favourite artists&lt;a href=&quot;#Favourite-artists-6&quot; aria-label=&quot;Favourite artists 6 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The Birthday Party&lt;/li&gt;
&lt;li&gt;Kleenex&lt;/li&gt;
&lt;li&gt;Gang of Four&lt;/li&gt;
&lt;li&gt;The Drums&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2017&quot; style=&quot;position:relative;&quot;&gt;2017&lt;a href=&quot;#2017&quot; aria-label=&quot;2017 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Finally-freed-of-18-hour-days-began-to-build-a-social-life-again&quot; style=&quot;position:relative;&quot;&gt;Finally freed of 18 hour days, began to build a social life again&lt;a href=&quot;#Finally-freed-of-18-hour-days-began-to-build-a-social-life-again&quot; aria-label=&quot;Finally freed of 18 hour days began to build a social life again permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Free from Bill, I felt like I could actually live life again. I started getting back into exercising, meeting new people and just having fun again.&lt;/p&gt;
&lt;p&gt;This was &lt;strong&gt;the best summer I&apos;ve ever had&lt;/strong&gt;. I was able to turn a really sleepy commuter school community into everyday feeling like a party. &lt;/p&gt;
&lt;img class=&quot;centered-image&quot; src=&quot;/img/blog/thoughts/decade-in-review/2017-setup.JPG&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;My minimal, brutalist workstation in Oakville, Ontario. Not by choice.&lt;/p&gt;
&lt;h3 id=&quot;Univjobs-makes-it-onto-Blog-Toronto--Toronto-Guardian-and-the-traffic-demolishes-our-tiny-AWS-t2micro&quot; style=&quot;position:relative;&quot;&gt;Univjobs makes it onto Blog Toronto &amp;#x26; Toronto Guardian, and the traffic demolishes our tiny AWS t2.micro&lt;a href=&quot;#Univjobs-makes-it-onto-Blog-Toronto--Toronto-Guardian-and-the-traffic-demolishes-our-tiny-AWS-t2micro&quot; aria-label=&quot;Univjobs makes it onto Blog Toronto  Toronto Guardian and the traffic demolishes our tiny AWS t2micro permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I was sitting in class when all of a sudden, 600 new people signed up for Univjobs within about 3 minutes. &lt;/p&gt;
&lt;p&gt;Looking at the traffic, we discovered that Univjobs had made it to the front page of &lt;a href=&quot;https://www.blogto.com/&quot;&gt;Blog Toronto&lt;/a&gt; with an article titled &quot;&lt;a href=&quot;https://www.blogto.com/tech/2018/04/students-jobs-toronto/&quot;&gt;There&apos;s a new way for students to look for jobs in Toronto&lt;/a&gt;&quot;.&lt;/p&gt;
&lt;p&gt;For &lt;em&gt;sure&lt;/em&gt;, the tiny little EC2 instance died, and in came hundreds of emails from people not getting their &lt;code class=&quot;language-text&quot;&gt;VerifyAccount&lt;/code&gt; email.&lt;/p&gt;
&lt;p&gt;This was the main event that turned me onto serverless architectures.&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; src=&quot;/img/blog/thoughts/decade-in-review/2017-stickers.png&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;Guerilla marketing. We printed off all kinds of Univjobs leaflets and put them everywhere. It didn&apos;t take long before we got a cease and desist from the school though.&lt;/p&gt;
&lt;h3 id=&quot;Stuff-I-made-4&quot; style=&quot;position:relative;&quot;&gt;Stuff I made&lt;a href=&quot;#Stuff-I-made-4&quot; aria-label=&quot;Stuff I made 4 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;While I was at Brock taking Robotics and Discrete Event Simulation, I wrote and recorded &lt;a href=&quot;https://debutante-band.bandcamp.com/releases&quot;&gt;Debutante&lt;/a&gt;, a gutteral post-punk album.&lt;/li&gt;
&lt;li&gt;Towards that end of the year, I did &lt;a href=&quot;https://cyanidecanaries.bandcamp.com/album/candy-body&quot;&gt;Candy Body&lt;/a&gt;. This has been the last bit of music I&apos;ve formally released.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Favourite-artists-7&quot; style=&quot;position:relative;&quot;&gt;Favourite artists&lt;a href=&quot;#Favourite-artists-7&quot; aria-label=&quot;Favourite artists 7 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The Wolfgang Press&lt;/li&gt;
&lt;li&gt;The Fall&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2018&quot; style=&quot;position:relative;&quot;&gt;2018&lt;a href=&quot;#2018&quot; aria-label=&quot;2018 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Graduated-from-collegeuniversity&quot; style=&quot;position:relative;&quot;&gt;Graduated from college/university&lt;a href=&quot;#Graduated-from-collegeuniversity&quot; aria-label=&quot;Graduated from collegeuniversity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After 4 and half years of school, 3 co-op jobs, and 8 different apartments, I had finally finished college and university obtaining both my Bachelor&apos;s degree in Computer Science and a Diploma in Internet Communications Technology.&lt;/p&gt;
&lt;h3 id=&quot;Focused-on-Univjobs-and-side-projects-to-pay-rent&quot; style=&quot;position:relative;&quot;&gt;Focused on Univjobs and side-projects to pay rent&lt;a href=&quot;#Focused-on-Univjobs-and-side-projects-to-pay-rent&quot; aria-label=&quot;Focused on Univjobs and side projects to pay rent permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After school, I had to figure out if I wanted to pursue Univjobs or get a real job. For a while, I was able to pay my rent by working as an independent freelancer, but I really hated the aspect of trying to find work and land contracts rather than just focusing on doing good work, so I got a real job.&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; src=&quot;/img/blog/thoughts/decade-in-review/2018-interview.png&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;Univjobs television interview.&lt;/p&gt;
&lt;h3 id=&quot;Started-work-at-Dev6&quot; style=&quot;position:relative;&quot;&gt;Started work at Dev6&lt;a href=&quot;#Started-work-at-Dev6&quot; aria-label=&quot;Started work at Dev6 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Dev6 is a small front-end consultancy in Mississauga. I worked here for about 8 months and coded mostly in TypeScript on Angular projects. It was also here that I met Sean Hopen, a senior consultant who would introduce me to Uncle Bob, TDD, DDD, and clean coding.&lt;/p&gt;
&lt;h3 id=&quot;Favourite-artists-8&quot; style=&quot;position:relative;&quot;&gt;Favourite artists&lt;a href=&quot;#Favourite-artists-8&quot; aria-label=&quot;Favourite artists 8 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Cypress Hill&lt;/li&gt;
&lt;li&gt;Sleaford Mods&lt;/li&gt;
&lt;li&gt;Mac Demarco&lt;/li&gt;
&lt;li&gt;Wu-Tang Clan&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2019&quot; style=&quot;position:relative;&quot;&gt;2019&lt;a href=&quot;#2019&quot; aria-label=&quot;2019 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Focused-on-software-architecture-and-domain-driven-design&quot; style=&quot;position:relative;&quot;&gt;Focused on software architecture and domain-driven design&lt;a href=&quot;#Focused-on-software-architecture-and-domain-driven-design&quot; aria-label=&quot;Focused on software architecture and domain driven design permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;2-ish years into working on Univjobs, I realized that we were having a lot of troubles pushing out new features because the codebase had just gotten so massive and disorganized.&lt;/p&gt;
&lt;p&gt;I ended up spending over $500 in software design and architecture books, took a couple of months to read &apos;em, then refactored Univjobs to TypeScript with Domain-Driven Design.&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; src=&quot;/img/blog/thoughts/decade-in-review/2019-books.png&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;A growing collection of software design books.&lt;/p&gt;
&lt;h3 id=&quot;Started-blogging--khalilstemmlercom&quot; style=&quot;position:relative;&quot;&gt;Started blogging @ khalilstemmler.com&lt;a href=&quot;#Started-blogging--khalilstemmlercom&quot; aria-label=&quot;Started blogging  khalilstemmlercom permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;During the time that I was reading these books and improving the terrible code that I had written, I realized that there are a lot of common pitfalls in building large-scale applications that the JavaScript community has neglected.&lt;/p&gt;
&lt;p&gt;Half in order to solidify my learning, and half to give back and raise awareness to software craftsmanship in the JS community, I started writing about &lt;a href=&quot;/articles/categories/domain-driven-design/&quot;&gt;DDD&lt;/a&gt;, &lt;a href=&quot;/articles/categories/enterprise-node-type-script/&quot;&gt;Enterprise Node.js / TypeScript&lt;/a&gt;, and software design at khalilstemmler.com.&lt;/p&gt;
&lt;p&gt;Over the course of the year, traffic has grown to approximately 700 visitors per day, which I&apos;m really proud of. I&apos;m planning on keeping that momentum going in 2020 with topics about GraphQL, DDD, TypeScript, and Event Sourcing.&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; src=&quot;/img/blog/thoughts/decade-in-review/2019-early-setup.JPG&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;I was finally able to afford moving into an apartment with natural lighting. About time.&lt;/p&gt;
&lt;h3 id=&quot;Univjobs-gets-government-funding&quot; style=&quot;position:relative;&quot;&gt;Univjobs gets government funding&lt;a href=&quot;#Univjobs-gets-government-funding&quot; aria-label=&quot;Univjobs gets government funding permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;While on paid vacation, my co-founder called me to tell me that Univjobs secured OCE funding from the Government of Canada. &lt;/p&gt;
&lt;p&gt;I quit my work at Dev6 and focused on Univjobs full-time.&lt;/p&gt;
&lt;p&gt;Unfortunately, it didn&apos;t go so well, particularly because we were building a two-sided marketplace. This left us in a chicken-and-egg scenario where we were left to figure out how to get students as well as how to get employers and jobs at the same time.&lt;/p&gt;
&lt;p&gt;We came up with a good plan to build a Campus Reps referral program where every referral a campus rep got, they could make $1.&lt;/p&gt;
&lt;p&gt;Testing it out with a few reps, we noticed that it was incredibly effective. In about 5 minutes of work, reps were able to get 80-100 signups and make around $60 bucks, easy.&lt;/p&gt;
&lt;p&gt;Unfortunately, due to budget cuts, thanks to the Ford government, we never actually saw the OCE money that we were waiting on.&lt;/p&gt;
&lt;h3 id=&quot;Started-writing-solidbookio&quot; style=&quot;position:relative;&quot;&gt;Started writing solidbook.io&lt;a href=&quot;#Started-writing-solidbookio&quot; aria-label=&quot;Started writing solidbookio permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;On occasion, I would work out of an entrepreneurship hub in Mississauga. It was there that I met Eric Rafat, founder of &lt;a href=&quot;https://www.foundersbeta.com/&quot;&gt;FoundersBeta&lt;/a&gt;. Eric saw my website traffic and convinced me to take my writing more seriously and even attempt to build a product to sell as well.&lt;/p&gt;
&lt;p&gt;That&apos;s when I got the idea for &lt;a href=&quot;https://solidbook.io&quot;&gt;solidbook.io - The Software Design and Architecture Handbook&lt;/a&gt;. I wanted to consolidate everything that I thought every developer should know about software design and architecture into one resource instead of having it split across the 15 books I had to buy to learn it.&lt;/p&gt;
&lt;p&gt;To my surprise, people started pre-ordering the book. Eventually, I started pulling in around $2/3K per month on book sales and was able to pay my rent without Univjobs. &lt;/p&gt;
&lt;p&gt;Today, finishing solidbook.io is one of my primary goals of 2020.&lt;/p&gt;
&lt;h3 id=&quot;Co-founder-leaves-Univjobs&quot; style=&quot;position:relative;&quot;&gt;Co-founder leaves Univjobs&lt;a href=&quot;#Co-founder-leaves-Univjobs&quot; aria-label=&quot;Co founder leaves Univjobs permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We got so close to securing investment for Univjobs. We were able to convince a UK investor to fund our $500K seed round by explaining that we would use the money to grow the heck out of the student side with the Campus Rep software.&lt;/p&gt;
&lt;p&gt;Unfortunately for the rest of the team, our CEO ghosted the entire team for weeks and neglected to answer phone calls. &lt;/p&gt;
&lt;p&gt;About a week into the ghosting, the site went down entirely because of non-payment. Charles, our CEO, was the only one who had access to pay the AWS bill, but no one could reach him.&lt;/p&gt;
&lt;p&gt;A week later, he called a team meeting to make an announcement. The announcement was that he was considering taking a job at Lyft late-2020 and didn&apos;t feel like doing Univjobs anymore. &lt;/p&gt;
&lt;p&gt;It was quite a shame because we were right at the gates of funding. Although I feel like it was for the best because remote communication was poor, a lot of trust was broken, and morale on the team was very low.&lt;/p&gt;
&lt;p&gt;Everyone went their separate ways, and by the end of it, our first startup company Univjobs grew to 5000 students and a couple hundred employers in about 2 and a half years.&lt;/p&gt;
&lt;h3 id=&quot;Started-at-Apollo-GraphQL&quot; style=&quot;position:relative;&quot;&gt;Started at Apollo GraphQL&lt;a href=&quot;#Started-at-Apollo-GraphQL&quot; aria-label=&quot;Started at Apollo GraphQL permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Around the same time that I was trying to decide whether to continue working on Univjobs, &lt;a href=&quot;https://twitter.com/peggyrayzis&quot;&gt;Peggy Rayzis&lt;/a&gt; discovered my blog through &lt;a href=&quot;https://twitter.com/taniarascia&quot;&gt;Tania Rascia&apos;s&lt;/a&gt; &quot;&lt;a href=&quot;https://www.taniarascia.com/developer-blogs-to-follow-2019/&quot;&gt;Developer Blogs to Follow (2019)&lt;/a&gt;&quot; list and pitched the idea of working as a Developer Advocate for &lt;a href=&quot;https://www.apollographql.com/&quot;&gt;Apollo GraphQL&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Dropping Univjobs and choosing Apollo was a no-brainer. In October, I flew to San Francisco on my own for the first to meet the team and attend &lt;a href=&quot;https://summit.graphql.com/&quot;&gt;GraphQL Summit 2019&lt;/a&gt;.&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; src=&quot;/img/blog/thoughts/decade-in-review/california.jpeg&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;First time ever being to California. First time ever traveling to another country by myself.&lt;/p&gt;
&lt;p&gt;Great times, lots of learning, lots of GraphQL, and lots of karaoke.&lt;/p&gt;
&lt;p&gt;I&apos;m really excited about 2020 and the opportunity to work with Apollo, work on cool projects, meet developers around the world, learn from others, and help people be successful with Apollo, GraphQL, TypeScript, and DDD.&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; src=&quot;/img/blog/thoughts/decade-in-review/2019-graphql-summit.jpg&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;It&apos;s realzies. Look out, 2020 :)&lt;/p&gt;
&lt;h3 id=&quot;Favourite-artists-9&quot; style=&quot;position:relative;&quot;&gt;Favourite artists&lt;a href=&quot;#Favourite-artists-9&quot; aria-label=&quot;Favourite artists 9 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Jonathan Fire Eater&lt;/li&gt;
&lt;li&gt;Ghostface Killah&lt;/li&gt;
&lt;li&gt;MF Doom&lt;/li&gt;
&lt;li&gt;Part-Time&lt;/li&gt;
&lt;li&gt;John Maus&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;People-weve-lost-this-decade&quot; style=&quot;position:relative;&quot;&gt;People we&apos;ve lost this decade&lt;a href=&quot;#People-weve-lost-this-decade&quot; aria-label=&quot;People weve lost this decade permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Mark E. Smith&lt;/li&gt;
&lt;li&gt;Stewart Lupton&lt;/li&gt;
&lt;li&gt;Rowland S. Howard&lt;/li&gt;
&lt;li&gt;James Gandolfini&lt;/li&gt;
&lt;li&gt;Stan Lee&lt;/li&gt;
&lt;li&gt;Stephen Hillenburg&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Why Event-Based Systems? | Enterprise Node.js + TypeScript]]></title><description><![CDATA[There are several ways to design systems. When I first starting building applications, I would start out with the database. Eventually, I…]]></description><link>https://khalilstemmler.com/articles/enterprise-typescript-nodejs/why-event-based-systems/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/enterprise-typescript-nodejs/why-event-based-systems/</guid><pubDate>Fri, 27 Dec 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;There are several ways to design systems. When I first starting building applications, I would start out with the database. Eventually, I realized that the view dictates the data, so I moved to starting out with the UI. Then I realized that I was failing to represent a lot of important business rules, so I began to search for something else.&lt;/p&gt;
&lt;p&gt;Eventually I found &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design&lt;/a&gt; and starting building applications by first understanding the domain, then working upwards from the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;domain layer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I then realized the utility of &lt;a href=&quot;/articles/typescript-domain-driven-design/chain-business-logic-domain-events/&quot;&gt;domain events&lt;/a&gt; and the fact that you can illustrate an entire business&apos;s operations on a timeline with domain events.&lt;/p&gt;
&lt;p&gt;Designing systems from domain events instead of columns in a database, endpoints on an API, or components in a view, has so many benefits.&lt;/p&gt;
&lt;p&gt;Here are just a few.&lt;/p&gt;
&lt;h2 id=&quot;Communication&quot; style=&quot;position:relative;&quot;&gt;Communication&lt;a href=&quot;#Communication&quot; aria-label=&quot;Communication permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Thinking in terms of domain events is the closest we can get to expressing what happens in the real world. Features can be communicated by non-technical folk as a series of domain events.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;UserRegistered -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; EmailVerificationSent -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; EmailVerified&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Auditing--Reasoning&quot; style=&quot;position:relative;&quot;&gt;Auditing &amp;#x26; Reasoning&lt;a href=&quot;#Auditing--Reasoning&quot; aria-label=&quot;Auditing  Reasoning permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When we represent a system using events, we can reason about the way that the system changed over time since the current state is computed by applying all of the domain events that ever occurred. In some domains, this is mandatory for audits.&lt;/p&gt;
&lt;h2 id=&quot;Estimates&quot; style=&quot;position:relative;&quot;&gt;Estimates&lt;a href=&quot;#Estimates&quot; aria-label=&quot;Estimates permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Software can be a very creatively unbounded process. Find and count all the &lt;code class=&quot;language-text&quot;&gt;views&lt;/code&gt; (read models) that present data and &lt;code class=&quot;language-text&quot;&gt;commands&lt;/code&gt; (write models) that change the system and cause domain events, then measure their complexity.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;The views and commands that a system needs in order to be complete are called &quot;Use Cases&quot; and adhere to the &lt;a href=&quot;/articles/oop-design-principles/command-query-segregation/&quot;&gt;Command-Query Segregation&lt;/a&gt; design principle. Read &quot;&lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;Better Software Design with Application Layer Use Cases | Enterprise Node.js + TypeScript&lt;/a&gt;&quot; to learn more about how to design with use cases.&lt;/p&gt;
&lt;h2 id=&quot;Scalability&quot; style=&quot;position:relative;&quot;&gt;Scalability&lt;a href=&quot;#Scalability&quot; aria-label=&quot;Scalability permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Sometimes, in large applications- a single transaction might need to pass through or notify several other systems. In high-traffic scenarios, instead of blocking an async call, we introduce &quot;&lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Eventual_consistency&quot;&gt;Eventual Consistency&lt;/a&gt;&quot; as a way to enable systems to &quot;catch up&quot; eventually.&lt;/p&gt;
&lt;h2 id=&quot;Complexity&quot; style=&quot;position:relative;&quot;&gt;Complexity&lt;a href=&quot;#Complexity&quot; aria-label=&quot;Complexity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Business rules are often missed in &lt;a href=&quot;/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;CRUD-first design&lt;/a&gt;. In order to avoid unmaintainable &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;else&lt;/code&gt; statements and &lt;a href=&quot;/wiki/anemic-domain-model/&quot;&gt;anemic domain models&lt;/a&gt;, think in terms of events, the commands they sometimes invoke as side effects, and the preconditions that govern how and when they can be invoked.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Event-based architecture seems to be the common place to go when the problem we&apos;re solving with software gets really large. &lt;/p&gt;
&lt;p&gt;Unfortunately, there&apos;s a bit of a learning curve.&lt;/p&gt;
&lt;p&gt;If you&apos;re interested in learning event-based systems, here&apos;s what &lt;em&gt;I think&lt;/em&gt; the general learning path looks like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get really good at one programming language to the point where it feels like breathing for you.&lt;/li&gt;
&lt;li&gt;Understand what an &lt;a href=&quot;/wiki/anemic-domain-model/&quot;&gt;anemic domain model&lt;/a&gt; looks like and if you have one.&lt;/li&gt;
&lt;li&gt;Learn about Event Storming and how it can help you plan a project using events.&lt;/li&gt;
&lt;li&gt;Learn &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design concepts&lt;/a&gt; like entities, value objects, aggregates, and domain events.&lt;/li&gt;
&lt;li&gt;Learn about CQRS and why you would want to use it in your DDD project.&lt;/li&gt;
&lt;li&gt;Learn about Event-Sourcing&lt;/li&gt;
&lt;li&gt;Build an application using DDD, CQRS, and Event-Sourcing.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[How Apollo REST Data Source Deduplicates and Caches API calls [Deep Dive]]]></title><description><![CDATA[Quite honestly, I don't know if I really enjoy writing optimization code. I'm not saying that I don't like optimized code- I'm saying that…]]></description><link>https://khalilstemmler.com/blogs/graphql/how-apollo-rest-data-source-caches-api-calls/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/graphql/how-apollo-rest-data-source-caches-api-calls/</guid><pubDate>Sat, 14 Dec 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Quite honestly, I don&apos;t know if I really enjoy writing &lt;em&gt;optimization code&lt;/em&gt;. I&apos;m not saying that I don&apos;t like optimized code- I&apos;m saying that &lt;em&gt;optimization code&lt;/em&gt; tends to be the last thing that I need to do, has the potential to degrade readability a little bit, and can be pretty challenging to implement. Not only that, I just don&apos;t get as excited at the opportunity to optimize something as I do when I get the opportunity to codify things relevant to the business through domain layer code and use cases.&lt;/p&gt;
&lt;p&gt;But alas, it&apos;s something that needs to be done.&lt;/p&gt;
&lt;p&gt;And that&apos;s what I think Apollo has done really well with their tooling. They&apos;ve listened to the community and figured out the common tasks in hooking up a GraphQL server in production that aren&apos;t so fun (but totally necessary), and done a lot of that hard stuff for us so that we can &lt;em&gt;start out with an optimized GraphQL server&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Here&apos;s what we&apos;ll learn by the end of this article:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Potential ways to resolve data for a GraphQL endpoint using RESTful APIs.&lt;/li&gt;
&lt;li&gt;Why Apollo&apos;s REST Data Source library is a better choice than a wrapped HTTP client library.&lt;/li&gt;
&lt;li&gt;How Request Deduplication works in REST Data Source.&lt;/li&gt;
&lt;li&gt;How Resource Caching works in REST Data Source.&lt;/li&gt;
&lt;li&gt;How you can use the &lt;a href=&quot;https://www.npmjs.com/package/apollo-server-caching&quot;&gt;apollo-server-caching&lt;/a&gt; library to implement your own caching logic.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;Resolving-data-from-a-RESTful-API&quot; style=&quot;position:relative;&quot;&gt;Resolving data from a RESTful API&lt;a href=&quot;#Resolving-data-from-a-RESTful-API&quot; aria-label=&quot;Resolving data from a RESTful API permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you&apos;re thinking about running a Apollo GraphQL server, a common setup is to resolve data from an external REST API.&lt;/p&gt;
&lt;p&gt;Going that route, you might have heard of the &lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/data/data-sources/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=how_datasources_work&quot;&gt;Apollo REST Data Source&lt;/a&gt; library. &lt;/p&gt;
&lt;p&gt;Using it, you can write custom data-fetching methods in order to resolve data from your external RESTful services. The image below depicts a potential architecture.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/graphql/rest-data-sources/rest-data-source-architecture.svg&quot; alt=&quot;Apollo RESTDataSource architecture example&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Example architecture of a client application connected to a GraphQL server resolving data from 4 RESTful API services.&lt;/p&gt;
&lt;p&gt;Going through the &lt;a href=&quot;https://www.apollographql.com/docs/tutorial/introduction?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=how_datasources_work&quot;&gt;Apollo full-stack tutorial&lt;/a&gt;, the Apollo Docs recommend that we use the &lt;code class=&quot;language-text&quot;&gt;RESTDataSource&lt;/code&gt; library when trying to fetch data from an external REST API.&lt;/p&gt;
&lt;p&gt;We can get this to work in the following 3 steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ol&gt;
&lt;li&gt;Subclassing the &lt;code class=&quot;language-text&quot;&gt;RESTDataSource&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Setting the &lt;code class=&quot;language-text&quot;&gt;BaseURL&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Writing data fetching methods that utilize the parent class&apos;s &lt;code class=&quot;language-text&quot;&gt;get&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;post&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;put&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;patch&lt;/code&gt; (and more) in order to fetch data from the external REST API.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A very simple example of a &lt;code class=&quot;language-text&quot;&gt;RESTDataSource&lt;/code&gt; subclass might look like this:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;datasources/vinyl.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; RESTDataSource &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;apollo-datasource-rest&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Vinyl &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../models/vinyl&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; VinylCollection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylAPI&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;RESTDataSource&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;baseURL &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;https://api.whitelabel.com/v2/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getAllVinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;VinylCollection&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Utilize the `get` convenience method from the parent RESTDataSource class.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;vinyl&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Map the vinyl objects from the external API response into the format&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// that we need for our schema.&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;vinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;vinylReducer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// More data fetching code&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A common question becomes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;What is the advantage of using the &lt;code class=&quot;language-text&quot;&gt;RESTDataSource&lt;/code&gt; library over using an abstracted HTTP client?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Moreover, why do we need to use &lt;code class=&quot;language-text&quot;&gt;RESTDataSource&lt;/code&gt;? Couldn&apos;t we just use Axios and write our own &lt;code class=&quot;language-text&quot;&gt;get&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;post&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;patch&lt;/code&gt;, etc convenience methods if and when we feel like it?&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;datasources/vinyl.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Using axios instead&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; axios &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;axios&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Vinyl &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../models/vinyl&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; VinylCollection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylAPI&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;RESTDataSource&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;baseURL &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;https://api.whitelabel.com/v2/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getAllVinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;VinylCollection&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;axios&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; method&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;GET&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;baseURL&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;vinyl&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;vinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;vinylReducer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You could, but you&apos;d be missing out on some stuff.&lt;/p&gt;
&lt;p&gt;Today I learned that &lt;code class=&quot;language-text&quot;&gt;RESTDataSource&lt;/code&gt; comes with &lt;strong&gt;two awesome performance optimizations&lt;/strong&gt; out of the box:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Request Deduplication and Resource Caching.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;Request-Deduplication&quot; style=&quot;position:relative;&quot;&gt;Request Deduplication&lt;a href=&quot;#Request-Deduplication&quot; aria-label=&quot;Request Deduplication permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Request deduplication prevents double-invoking HTTP calls in rapid succession.&lt;/p&gt;
&lt;p&gt;That&apos;s a common enough problem if your some types in your resolvers rely on the same underlying API call in order to resolve fields.&lt;/p&gt;
&lt;p&gt;This chatty, rapid-fire behaviour is the type of thing that &lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/data/data-sources/#what-about-dataloader&quot;&gt;Facebook&apos;s DataLoader&lt;/a&gt; does &lt;em&gt;really well&lt;/em&gt; with loading data from an ORM or an in-memory datastore, but isn&apos;t as effective when dealing with RESTful API calls that go out onto the network and stress your service endpoints.&lt;/p&gt;
&lt;p&gt;Deduplicating &lt;u&gt;the API requests themselves&lt;/u&gt; fixes that.&lt;/p&gt;
&lt;h3 id=&quot;How-Request-Deduplication-works-in-REST-Data-Source&quot; style=&quot;position:relative;&quot;&gt;How Request Deduplication works in REST Data Source&lt;a href=&quot;#How-Request-Deduplication-works-in-REST-Data-Source&quot; aria-label=&quot;How Request Deduplication works in REST Data Source permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/apollographql/apollo-server/tree/master/packages/apollo-datasource-rest&quot;&gt;REST Data Source library&lt;/a&gt; uses a caching technique called &lt;a href=&quot;https://en.wikipedia.org/wiki/Memoization&quot;&gt;memoization&lt;/a&gt; in order to cache &lt;strong&gt;the entire Promise&lt;/strong&gt; invoked when we make a request to a resource. We hold onto the &lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt; for any request to an external RESTful resource in a &lt;code class=&quot;language-text&quot;&gt;Map&amp;lt;string, Promise&amp;lt;any&amp;gt;&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Memoization&lt;/b&gt;: A specific form of caching where for an indeterministic (and potentially expensive) operation, we save the results and return it from memory in subsequent invocations. Check out &lt;a target=&quot;_blank&quot; href=&quot;https://medium.com/@bluepnume/async-javascript-is-much-more-fun-when-you-spend-less-time-thinking-about-control-flow-8580ce9f73fc&quot;&gt;this article on &quot;How to Memoize Async Functions in JavaScript&quot;&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;src/RESTDataSource.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;RESTDataSource&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TContext &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DataSource&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 
  memoizedResults &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When a &lt;code class=&quot;language-text&quot;&gt;GET&lt;/code&gt; request comes in, we construct a &lt;em&gt;cache key&lt;/em&gt; for that request by looking at the URL:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;RESTDataSource&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TContext &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DataSource&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cacheKeyFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That url is what we&apos;re going to use as the &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; &lt;em&gt;key&lt;/em&gt; for the &lt;code class=&quot;language-text&quot;&gt;Map&lt;/code&gt; that holds our memoized requests.&lt;/p&gt;
&lt;p&gt;So if we make a request to &lt;code class=&quot;language-text&quot;&gt;https://api.kittens/v2/all?sort_by=cuteness&lt;/code&gt;, that becomes our key. &lt;/p&gt;
&lt;p&gt;Now here&apos;s the cool part.&lt;/p&gt;
&lt;p&gt;Depending on if the request was a &lt;a href=&quot;/articles/oop-design-principles/command-query-segregation/&quot;&gt;query&lt;/a&gt;-like HTTP verb like GET, we&apos;ll check to see if there&apos;s a memoized &lt;code class=&quot;language-text&quot;&gt;Promise&amp;lt;any&amp;gt;&lt;/code&gt; by looking it up using the cache key. If there&apos;s already a &lt;code class=&quot;language-text&quot;&gt;Promise&amp;lt;Request&amp;gt;&lt;/code&gt; in progress for that cache key, just return that Promise that we know will resolve to the same thing we&apos;re already asking for from a previous request. Otherwise, we&apos;ll perform the request and memoize it so that it can be deduplicated for subsequent requests.&lt;/p&gt;
&lt;p&gt;However, if we issued a &lt;a href=&quot;/articles/oop-design-principles/command-query-segregation/&quot;&gt;command&lt;/a&gt;-like request like &lt;code class=&quot;language-text&quot;&gt;DELETE&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;POST&lt;/code&gt;, let&apos;s remove that item from the memoization cache because the next time we retrieve it, we can expect it&apos;s value to be different.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;src/RESTDataSource.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;RESTDataSource&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TContext &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DataSource&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; fetch&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    init&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; RequestInit &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      path&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      params&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; URLSearchParamsInit&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 

    &lt;span class=&quot;token comment&quot;&gt;// If the request is a QUERY, see if we can get the memoized&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// result to prevent invoking another API call for a resource that hasn&apos;t&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// yet changed.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;method &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;GET&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; promise &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;memoizedResults&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cacheKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;promise&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; promise&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Didn&apos;t find it, just invoke the request normally and then save&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// the request to our memoization cache.&lt;/span&gt;
      promise &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;performRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;memoizedResults&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cacheKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; promise&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; promise&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// If the request is a COMMAND, delete the item from our memoization&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// cache (because we&apos;re about to issue a side-effect) and then perform the request.&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;memoizedResults&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cacheKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;performRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To illustrate that this works corrrectly, here&apos;s a test case straight from the Apollo REST Data Source library.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;src/__tests__/RESTDataSource.test.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt; &lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;memoization&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;deduplicates requests with the same cache key&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dataSource &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;RESTDataSource&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        baseURL &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;https://api.example.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;getFoo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; a &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      dataSource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;httpCache &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; httpCache&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      fetch&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mockJSONResponseOnce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dataSource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFoo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dataSource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFoo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fetch&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mock&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;calls&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fetch&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mock&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;calls&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;https://api.example.com/foo?a=1&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you fired the same request of one that was &lt;em&gt;already in flight but not resolved yet&lt;/em&gt; you’d only generate one Promise (and one fetch)!&lt;/p&gt;
&lt;h2 id=&quot;Resource-Caching&quot; style=&quot;position:relative;&quot;&gt;Resource Caching&lt;a href=&quot;#Resource-Caching&quot; aria-label=&quot;Resource Caching permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As for the actual responsibility of caching in REST Data Source, that falls into the lap of an Apollo-implemented &lt;a href=&quot;https://www.npmjs.com/package/apollo-server-caching&quot;&gt;Apollo Server Cache&lt;/a&gt; called &lt;code class=&quot;language-text&quot;&gt;HTTPClient&lt;/code&gt;.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Resource cache&lt;/b&gt;: The more traditional understanding of caching. We save a fetched resource in a storage medium more efficient at retrievals than the initial mechanism we used to retrieve it. For example, fetching an object from memory is faster than reaching into a database (disk) to fetch it. Also, fetching an object from memory is also often faster than making a network call to an external resource.&lt;/p&gt;
&lt;h3 id=&quot;How-it-works&quot; style=&quot;position:relative;&quot;&gt;How it works&lt;a href=&quot;#How-it-works&quot; aria-label=&quot;How it works permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When &lt;code class=&quot;language-text&quot;&gt;RESTDataSource&lt;/code&gt; invokes &lt;code class=&quot;language-text&quot;&gt;performRequest&lt;/code&gt;, it uses a class called &lt;code class=&quot;language-text&quot;&gt;HTTPCache&lt;/code&gt; which is composed with a &lt;code class=&quot;language-text&quot;&gt;KeyValueCache&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;KeyValueCache&lt;/code&gt; is a &lt;em&gt;powerful&lt;/em&gt; interface that Apollo Server uses internally to provide a caching store for the Data Sources.&lt;/p&gt;
&lt;p&gt;In the following code (that powers &lt;code class=&quot;language-text&quot;&gt;RESTDataSource&lt;/code&gt;), Apollo uses an &lt;code class=&quot;language-text&quot;&gt;InMemoryLRUCache&lt;/code&gt;, which is a valid subtype of the &lt;code class=&quot;language-text&quot;&gt;KeyValueCache&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;src/HTTPCache.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HTTPCache&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; keyValueCache&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; KeyValueCache&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; httpFetch&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; fetch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// You can pass in your own cache, but Apollo will use an&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// InMemoryLRUCache by default&lt;/span&gt;
    keyValueCache&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; KeyValueCache &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InMemoryLRUCache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    httpFetch&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; fetch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fetch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keyValueCache &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PrefixingKeyValueCache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      keyValueCache&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&apos;httpcache:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;httpFetch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; httpFetch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When a request comes in, we run similar logic to that of which we ran in our memoization cache, but this time, we&apos;re in control of if the request goes out onto the wire or not.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;src/HTTPCache.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HTTPCache&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 
  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    options&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      cacheKey&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      cacheOptions&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; CacheOptions
        &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;response&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; CacheOptions &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Response&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/**
     * 1. Create the cache key. You can either supply a cache key or leave it blank
     * and Apollo will use the URL of the request as the key.
     */&lt;/span&gt; 
  
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cacheKey &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cacheKey &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cacheKey &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/**
     * 2. Using that key, see if the cache has the value already.
     */&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; entry &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keyValueCache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cacheKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/**
     * 3. If it doesn&apos;t already have the response, we&apos;ll need to
     * get it, store the response in the cache, and return the 
     * response.
     */&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;entry&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;httpFetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; policy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CachePolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;policyRequestFrom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;policyResponseFrom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;storeResponseAndReturnClone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        response&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        policy&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        cacheKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cacheOptions&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/**
     * 4. Returns the object from the cache (respecting any
     * cache invalidation policies).
     */&lt;/span&gt; 

    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;You can read this file and peruse around the rest of the codebase for the Apollo REST Data Source library &lt;a href=&quot;https://github.com/apollographql/apollo-server/blob/master/packages/apollo-datasource-rest/src/HTTPCache.ts&quot;&gt;here on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Out of the box, this thing does a &lt;em&gt;LOT&lt;/em&gt;. But if you want to roll your own cache, or if you need to &lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/data/data-sources/?utm_source=khalil&amp;#x26;utm_medium=article&amp;#x26;utm_campaign=how_datasources_work#using-memcachedredis-as-a-cache-storage-backend&quot;&gt;hook several GraphQL endpoints up to Redis or Memcached&lt;/a&gt; for a single source of truth, that&apos;s totally possible as well.&lt;/p&gt;
&lt;h3 id=&quot;Making-your-own-cache&quot; style=&quot;position:relative;&quot;&gt;Making your own cache&lt;a href=&quot;#Making-your-own-cache&quot; aria-label=&quot;Making your own cache permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For REST Data Source, Apollo ships with it&apos;s own in-memory caching strategy called &lt;code class=&quot;language-text&quot;&gt;InMemoryLRUCache&lt;/code&gt;. While this is what &lt;code class=&quot;language-text&quot;&gt;HTTPCache&lt;/code&gt; that REST Data Source relies on, there&apos;s nothing stopping you from writing your own cache strategy.&lt;/p&gt;
&lt;p&gt;In order for Apollo to utilize your cache, all you need to do is write a class that implements the &lt;code class=&quot;language-text&quot;&gt;KeyValueCache&lt;/code&gt; interface and you&apos;re good to go.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;KeyValueCache&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ttl&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;You can get started implementing your own cache using the &lt;a href=&quot;https://www.npmjs.com/package/apollo-server-caching&quot;&gt;apollo-server-caching&lt;/a&gt; npm library.&lt;/p&gt;
&lt;h2 id=&quot;Summary&quot; style=&quot;position:relative;&quot;&gt;Summary&lt;a href=&quot;#Summary&quot; aria-label=&quot;Summary permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Apollo REST Data Source comes equipped with Request Deduplication and a Resource Cache&lt;/li&gt;
&lt;li&gt;Request Deduplication prevents multiple requests to the same resource from getting invoked using memoization.&lt;/li&gt;
&lt;li&gt;The Resource Cache prevents multiple requests to the same resource from getting sent out onto the wire.&lt;/li&gt;
&lt;li&gt;You can implement your own Resource Cache using the &lt;a href=&quot;https://www.npmjs.com/package/apollo-server-caching&quot;&gt;apollo-server-caching&lt;/a&gt; library.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https://twitter.com/TrevorJScheer&quot;&gt;Trevor Sheer&lt;/a&gt; for helping me understand the responsibility division between &lt;code class=&quot;language-text&quot;&gt;RESTDataSource&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;HTTPCache&lt;/code&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[No title]]></title><description><![CDATA[If what we ship to our server is a single executable file or script that runs our entire application in one process, we have a monolith on…]]></description><link>https://khalilstemmler.com/wiki/monolith/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/monolith/</guid><pubDate>Mon, 02 Dec 2019 04:05:26 GMT</pubDate><content:encoded>&lt;p&gt;If what we ship to our server is a single executable file or script that runs our entire application in one process, we have a monolith on our hands.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img style=&quot;max-width: 300px;&quot; src=&quot;/img/wiki/monolith/monolith-img-1.svg&quot; /&gt;
&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;A monolithic application containing modules from A to F.&lt;/p&gt;
&lt;p&gt;If for some reason, our application relies on another service that contains critical features or business logic for our core domain, it&apos;s no longer a monolith. It may be a &lt;em&gt;distributed monolith&lt;/em&gt;.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img style=&quot;max-width: 300px;&quot; src=&quot;/img/wiki/monolith/monolith-img-2.svg&quot; /&gt;
&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;An application that relies on a business-critical module running in a separate process is no longer a monolith.&lt;/p&gt;
&lt;h2 id=&quot;When-to-migrate-to-microservices&quot; style=&quot;position:relative;&quot;&gt;When to migrate to microservices&lt;a href=&quot;#When-to-migrate-to-microservices&quot; aria-label=&quot;When to migrate to microservices permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A monolith isn&apos;t always a bad thing. In fact, I would advocate for starting out with a monolith on  &lt;em&gt;most&lt;/em&gt; projects.&lt;/p&gt;
&lt;p&gt;Factors that can influence needing to break a monolith into microservices are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Growing team size.&lt;/li&gt;
&lt;li&gt;Clear understanding of the subdomains within the code and how they can be assigned to teams.&lt;/li&gt;
&lt;li&gt;Horizonal scaling required for select high-traffic or expensive to operate features in the application.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Difference-between-a-monorepo-and-a-monolith&quot; style=&quot;position:relative;&quot;&gt;Difference between a monorepo and a monolith&lt;a href=&quot;#Difference-between-a-monorepo-and-a-monolith&quot; aria-label=&quot;Difference between a monorepo and a monolith permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &lt;em&gt;monorepo&lt;/em&gt; is a code repository that we use to store several related repositories for a project. &lt;/p&gt;
&lt;p&gt;A monorepo can &lt;em&gt;become&lt;/em&gt; a monolith if when we run an application contained from within a monorepo, it has access to all the components needed in order for it to operate, and all those components are self-contained at runtime.&lt;/p&gt;
&lt;p&gt;If we needed to run several processes from within the monorepo in order for the application to work, it&apos;s no longer a monolith.&lt;/p&gt;
&lt;h2 id=&quot;Benefits&quot; style=&quot;position:relative;&quot;&gt;Benefits&lt;a href=&quot;#Benefits&quot; aria-label=&quot;Benefits permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Ease of local development.&lt;/li&gt;
&lt;li&gt;Ease of deployment.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Disadvantages&quot; style=&quot;position:relative;&quot;&gt;Disadvantages&lt;a href=&quot;#Disadvantages&quot; aria-label=&quot;Disadvantages permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Single point of failure.&lt;/li&gt;
&lt;li&gt;Checking in code can turn into a nightmare if the team size is large. Code conflicts might occur more frequently.&lt;/li&gt;
&lt;li&gt;For some applications, it doesn&apos;t scale well.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Books that Developers Should Read in 2020 [List]]]></title><description><![CDATA[Whether you’re a new developer or you’re fairly experienced as a programmer, you’ll come to realize that the amount of time you’ve worked at…]]></description><link>https://khalilstemmler.com/articles/software-professionalism/books-that-developers-should-read-in-2020/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/software-professionalism/books-that-developers-should-read-in-2020/</guid><pubDate>Fri, 22 Nov 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Whether you’re a new developer or you’re fairly experienced as a programmer, you’ll come to realize that the amount of time you’ve worked at a job isn’t the best way to determine your skill and knowledge as a programmer (I know, tell that to the recruiters 🤫).&lt;/p&gt;
&lt;p&gt;What you do in your spare time and how you choose to take learning into your own hands is what’s going to ultimately determine your success in this industry. That’s why it’s so important for us as developers to adopt a growth mindset.&lt;/p&gt;
&lt;p&gt;There are some excellent ways to learn and improve as a developer. Some of those ways are pair-programming, online courses, meetups, work experience, building projects and finding a mentor.&lt;/p&gt;
&lt;p&gt;One of my personal favorite ways to learn is to crack open a well-written book and try to absorb something from those who have distilled years of knowledge and insight into a permanent artifact.&lt;/p&gt;
&lt;p&gt;Here are my personal recommendations that I think all developers (especially junior ones) should read at some point. These books are all highly regarded by professionals in our industry and have the potential to leave a profound impact on the quality of your work and your speed of development &amp;#x26; learning.&lt;/p&gt;
&lt;p&gt;Some of them stray from the technical details and focus more on giving you practical rules about what it means to be a good developer on the interpersonal and professional level.&lt;/p&gt;
&lt;h2 id=&quot;1-Clean-Code&quot; style=&quot;position:relative;&quot;&gt;1. Clean Code&lt;a href=&quot;#1-Clean-Code&quot; aria-label=&quot;1 Clean Code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;by Robert C. Martin (Uncle Bob)&lt;/p&gt;
&lt;p&gt;After you overcome the basic challenges of development and get comfortable figuring out how to write code to solve problems, it’d be a good idea to take a look at this book. It turns out that making the code work the first time is actually the easy part. The hard part is making your code read well so that others are able to understand it and change it in the future.
Remember the last time you had to read code like this?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateIt&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;delta &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;delta&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; h &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; h
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Who knows what it really does. Code like this might work, but the moment we need to change it, we have to hope the author of the code is still in the company and pray that they are somehow able to decipher what they wrote potentially years ago.
When careful attention isn’t taken to write code that’s readable and maintainable, we end up with pockets of code like this that everyone is afraid to touch, and if it ever breaks, we’re in trouble.&lt;/p&gt;
&lt;p&gt;Uncle Bob’s “Clean Code” teaches you how to identify what clean code looks like compared to bad code, and it teaches you how to transform it into good code. A task like this sounds trivial to most, but you’d be surprised at how turning a just a few clean software design principles into habits can help you write much more professional and scalable code.&lt;/p&gt;
&lt;p&gt;We’re software craftspeople, you know. Building a house is not much different than building an application in principle. We need to pay attention to the details or else it can all become very expensive to fix in the future if not done right first time.&lt;/p&gt;
&lt;h2 id=&quot;2-The-Clean-Coder&quot; style=&quot;position:relative;&quot;&gt;2. The Clean Coder&lt;a href=&quot;#2-The-Clean-Coder&quot; aria-label=&quot;2 The Clean Coder permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;by Robert C. Martin (Uncle Bob)&lt;/p&gt;
&lt;p&gt;This book is not necessarily a technical book as it is a book for teaching you how to be a professional in this industry. Professionals are those who, when faced with challenges, uncertainty and pressure, will continue to treat creating software as a craft and will be determined to adhere to their professional values.&lt;/p&gt;
&lt;p&gt;The Clean Coder is full of practical advice on estimation, refactoring, testing, dealing with conflict, schedules, avoiding burnout, and much more. Trusted advice from someone who has spent decades doing this stuff.&lt;/p&gt;
&lt;p&gt;One of the best things it teaches, is how to have integrity as a developer, when to say “No” and how to say it.&lt;/p&gt;
&lt;p&gt;A book about professionalism.&lt;/p&gt;
&lt;h2 id=&quot;3-Refactoring&quot; style=&quot;position:relative;&quot;&gt;3. Refactoring&lt;a href=&quot;#3-Refactoring&quot; aria-label=&quot;3 Refactoring permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;by Martin Fowler&lt;/p&gt;
&lt;p&gt;Martin Fowler is one of my favorite authors. The first reason is that he’s hilarious. His approach to writing software books is unmistakably “Fowler”. The other reason is that he’s incredibly good at explaining complex topics, and doing so very simply, in a way that doesn’t fatigue you as a reader.&lt;/p&gt;
&lt;p&gt;Refactoring is a book that the creator of Ruby on Rails once said that you should “read before you write another line of code”. Fowler guides you through refactoring a simple application, introducing you to a number of techniques that he’s accumulated and cataloged over his years of consulting.&lt;/p&gt;
&lt;p&gt;Fowler shows you how to flip between coding and refactoring, how often you should be committing your code and when you should be writing your tests. Highly recommended. The latest version of this book was updated to present the examples in JavaScript, which was an added plus for me since it’s my favorite language.&lt;/p&gt;
&lt;p&gt;Half of this book serves as a reference guide, which you may or may not like- but I think it&apos;s important to be aware of how one piece of code can always be refactored to better serve the needs of its users tomorrow.&lt;/p&gt;
&lt;h2 id=&quot;4-Design-Patterns-Elements-of-Reusable-Object-Oriented-Software&quot; style=&quot;position:relative;&quot;&gt;4. Design Patterns: Elements of Reusable Object-Oriented Software&lt;a href=&quot;#4-Design-Patterns-Elements-of-Reusable-Object-Oriented-Software&quot; aria-label=&quot;4 Design Patterns Elements of Reusable Object Oriented Software permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;by Erich Gamma, Richard Helm, Ralph Johnson, &amp;#x26; John Vlissides&lt;/p&gt;
&lt;p&gt;This is the seminal book on Design Patterns. What are design patterns, you ask? Design Patterns are well-known solutions to commonly occurring problems in software development. If you’re familiar with the patterns, you’ll find that you’ll be able to greatly reduce the amount of time it takes you to put forth the solutions to those problems.&lt;/p&gt;
&lt;p&gt;Having a good awareness of design patterns also allows you to communicate your solutions effectively with other developers.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Yeah, I just used a Facade overtop of whichever database Adapter gets loaded from the Strategy.”
“Ahh! Gotcha.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yeah, it’s an older book. But it’s still one of the best for reference. If you’d like something on this topic that’s a bit more recent and friendly, I’d also recommend the good “&lt;strong&gt;Head First Design Patterns: A Brain-Friendly Guide&lt;/strong&gt;” by Eric Freeman and friends.&lt;/p&gt;
&lt;h2 id=&quot;5-Domain-Driven-Design-Tackling-Complexity-in-the-Heart-of-Software&quot; style=&quot;position:relative;&quot;&gt;5. Domain-Driven Design: Tackling Complexity in the Heart of Software&lt;a href=&quot;#5-Domain-Driven-Design-Tackling-Complexity-in-the-Heart-of-Software&quot; aria-label=&quot;5 Domain Driven Design Tackling Complexity in the Heart of Software permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;by Eric Evans&lt;/p&gt;
&lt;p&gt;In order for large code bases to continue to scale, we need to logically split up code into different parts. The idea is to partition your code in a way such that it would be possible for separate teams to work on those parts of your system without affecting anyone else.&lt;/p&gt;
&lt;p&gt;The underlying concept that enables moving your code base in this direction is Domain-Driven Design (DDD). It’s an approach to software development where we model the problems that exist in the “problem domain” (the real world) to a number of solution domains.&lt;/p&gt;
&lt;p&gt;DDD is incredibly important when a code base gets sufficiently large. Large enterprise companies employ DDD in order to assign teams to parts of the company’s code base.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/wiki/anemic/chart.svg&quot; alt=&quot;Anemic Domain Model&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Diagram showing when an &lt;a href=&quot;/wiki/anemic-domain-model/&quot;&gt;anemic model&lt;/a&gt; becomes cumbersome.&lt;/p&gt;
&lt;p&gt;Eric Evan’s coined the term “Ubiquitous Language”, which is the term for building a common, all-encompassing language between the developers, the domain experts and any other users or actors in the domain. By using this Ubiquitous Language, it ensures that the most important domain concepts are well understood and get modeled in the software.&lt;/p&gt;
&lt;p&gt;The book is a little more technical and challenging than the others, but if you get familiar with these concepts, you’ll be very well off in understanding how today’s largest companies keep their code bases manageable and scalable.&lt;/p&gt;
&lt;p&gt;The ideas presented are essential readings before wandering into microservices and all the challenges it will present to you.&lt;/p&gt;
&lt;h3 id=&quot;Alternative-recommendation&quot; style=&quot;position:relative;&quot;&gt;Alternative recommendation&lt;a href=&quot;#Alternative-recommendation&quot; aria-label=&quot;Alternative recommendation permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I’ve thought about this recommendation a little bit. Introduction to the DDD world is, in my opinion, extremely beneficial for Junior Developers. I believe this to be true because DDD introduces builds familiarity with software architecture, design principles and design patterns. It’s a great way to practically introduce yourself to a higher level of programming.&lt;/p&gt;
&lt;p&gt;That said, DDD is a large and challenging topic. For some readers, this book (the seminal “blue book”) by Eric Evans might be better treated as a reference. It was Eric Evans who wrote the first book on DDD.&lt;/p&gt;
&lt;p&gt;However, I also read &quot;DDD Distilled&quot; by Vaughn Vernon. It&apos;s good.&lt;/p&gt;
&lt;p&gt;It’s a really short and sweet intro to DDD, written in order to address the fact that most books on DDD are huge in size.&lt;/p&gt;
&lt;p&gt;Definitely try &quot;DDD Distilled&quot; instead. I think this book would be a lot better for most developers in order to get ramped up on the DDD essentials first. For more practical details on how to implement the concepts, refer back to “the blue book” and “the red book”.&lt;/p&gt;
&lt;h2 id=&quot;7-Clean-Architecture&quot; style=&quot;position:relative;&quot;&gt;7. Clean Architecture&lt;a href=&quot;#7-Clean-Architecture&quot; aria-label=&quot;7 Clean Architecture permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;by Robert C. Martin (Uncle Bob)&lt;/p&gt;
&lt;p&gt;What? Uncle Bob writes good books, ok?&lt;/p&gt;
&lt;p&gt;In school, there’s a lot of focus on algorithms and less focus on software design principles. I think it’s kind of unfortunate because in reality, you don’t encounter that many algorithm challenges too often. Instead, it’s more common that you’ll be faced with the challenge of structuring your code in a way that’s modular, flexible, readable and will allow you to add new features quickly when requirements change.
Clean Architecture is about the essential software design principles and patterns that you’ll be able to use in order to face these challenges.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/books-for-developers/clean-architecture.png&quot; alt=&quot;Clean Architecture&quot;&gt;&lt;/p&gt;
&lt;p&gt;Some of the best takeaways from this book are the cost of dependencies, stable vs. non-stable code and the SOLID principles: a way to write code so that it’s more understandable, flexible and maintainable.&lt;/p&gt;
&lt;p&gt;Other aspects of this book that were incredibly useful were concepts of “screaming architecture” and “packaging by component” which are opinions on how to organize your modules so that it practically screams to the reader exactly what the project is all about.&lt;/p&gt;
&lt;p&gt;This book goes well hand-in-hand with Domain-Driven Design, which is enabled through the use of a “Layered Architecture” or as Uncle Bob calls it, “The Clean Architecture” (also known as Ports and Adapters). A great book for anyone who wants to up their architecture chops and learn how to effectively design a system at a high level, and do the dance of dependencies at the detail level.&lt;/p&gt;
&lt;h2 id=&quot;8-The-Effective-Engineer&quot; style=&quot;position:relative;&quot;&gt;8. The Effective Engineer&lt;a href=&quot;#8-The-Effective-Engineer&quot; aria-label=&quot;8 The Effective Engineer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;by Edmond Lau&lt;/p&gt;
&lt;p&gt;Time is our single most valuable asset in life, and we should aim to be more efficient with it. It’s easy to get bogged down and spend a lot of time fixing bugs and wasting effort. Doing repeated work. Bleh. The Effective Engineer is all about getting more done in less time and removing repeated work.&lt;/p&gt;
&lt;p&gt;We can mitigate wasted time and effort on repetitive tasks through a framework called “leverage”.&lt;/p&gt;
&lt;p&gt;Leverage helps you identify the activities that you can do that produce the most disproportionate results- per unit of time invested. It’s a framework that can apply to anything, whether that be how you learn, how you code, how you debug… anything!&lt;/p&gt;
&lt;h2 id=&quot;9-The-Pragmatic-Programmer&quot; style=&quot;position:relative;&quot;&gt;9. The Pragmatic Programmer&lt;a href=&quot;#9-The-Pragmatic-Programmer&quot; aria-label=&quot;9 The Pragmatic Programmer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;by Andrew Hunt &amp;#x26; David Thomas&lt;/p&gt;
&lt;p&gt;Praised for being easy to follow and understand, The Pragmatic Programmer is a book that should be on the desktop of developers of all levels. Andrew and David are programmers that not only spent many years doing what they do, but paying attention to what they were doing as they were doing it, and then trying to determine if they could do that better.&lt;/p&gt;
&lt;p&gt;What came out of their years of introspection was this book, which introduces a number of essential programmer philosophies to follow throughout your career, like “programmers should have a “do it once, or automate” philosophy”.&lt;/p&gt;
&lt;p&gt;It includes simple yet detailed advice that you should carry with you in the back of your mind before you write another line of code or start a new project.&lt;/p&gt;
&lt;h2 id=&quot;Final-Words&quot; style=&quot;position:relative;&quot;&gt;Final Words&lt;a href=&quot;#Final-Words&quot; aria-label=&quot;Final Words permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Books really are some of the best tools to improve your knowledge and skills as a new programmer or Junior Developer. Books tend to have a really high return on investment; did you know you can make a lot of money programming? 😉&lt;/p&gt;
&lt;p&gt;These are just a few of the best books out there right now in 2019! None of them are really new, but that’s because programming has maintained the same general philosophies and best practices for years. As a professor I once had to say, “you can make a lot of money in this industry, you just have to read the damn manual”.&lt;/p&gt;
&lt;p&gt;Have you read any of these books? What did you think? Any books not on this list that you think newer developers would really benefit from reading? Let us know in the comments!&lt;/p&gt;
&lt;h2 id=&quot;Additional-Resources&quot; style=&quot;position:relative;&quot;&gt;Additional Resources&lt;a href=&quot;#Additional-Resources&quot; aria-label=&quot;Additional Resources permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here’s a list of some really excellent articles that cover some of the topics from these books. If you don’t quite have the time to invest in fully blown books right now, familiarizing yourself with these concepts might assist you in your journey to become a better developer!&lt;/p&gt;
&lt;h3 id=&quot;Architecture--software-design&quot; style=&quot;position:relative;&quot;&gt;Architecture &amp;#x26; software design&lt;a href=&quot;#Architecture--software-design&quot; aria-label=&quot;Architecture  software design permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Refactoring.guru
&lt;a href=&quot;https://refactoring.guru/&quot;&gt;https://refactoring.guru/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;SOLID Design Principles
&lt;a href=&quot;https://stackify.com/solid-design-principles/&quot;&gt;https://stackify.com/solid-design-principles/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;NodeJS and Good Practices
&lt;a href=&quot;https://blog.codeminer42.com/nodejs-and-good-practices-354e7d76362&quot;&gt;https://blog.codeminer42.com/nodejs-and-good-practices-354e7d76362&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Implementing the SOLID and the onion architecture in Node.js
&lt;a href=&quot;https://dev.to/remojansen/implementing-the-onion-architecture-in-nodejs-with-typescript-and-inversifyjs-10ad&quot;&gt;https://dev.to/remojansen/implementing-the-onion-architecture-in-nodejs-with-typescript-and-inversifyjs-10ad&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Better Software Design with Clean Architecture
&lt;a href=&quot;https://fullstackmark.com/post/11/better-software-design-with-clean-architecture&quot;&gt;https://fullstackmark.com/post/11/better-software-design-with-clean-architecture&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Clean Architecture
&lt;a href=&quot;http://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html&quot;&gt;http://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;Web-Development&quot; style=&quot;position:relative;&quot;&gt;Web Development&lt;a href=&quot;#Web-Development&quot; aria-label=&quot;Web Development permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://amazon.com/dp/1983065633&quot; title=&quot;css book&quot;&gt;CSS Visual Dictionary&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Make Illegal States Unrepresentable! - Domain-Driven Design w/ TypeScript]]></title><description><![CDATA[When we first learn how to code, we're typically most focused on making things work. We visualize the finished product as a coming together…]]></description><link>https://khalilstemmler.com/articles/typescript-domain-driven-design/make-illegal-states-unrepresentable/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/typescript-domain-driven-design/make-illegal-states-unrepresentable/</guid><pubDate>Thu, 21 Nov 2019 23:04:10 GMT</pubDate><content:encoded>&lt;p&gt;When we first learn how to code, we&apos;re typically most focused on making &lt;em&gt;things work&lt;/em&gt;. We visualize the finished product as a &lt;u&gt;coming together of several technologies&lt;/u&gt;. A common MVC-mental model for a full-stack web app is: &lt;strong&gt;database&lt;/strong&gt; + &lt;strong&gt;React app&lt;/strong&gt; + &lt;strong&gt;Express API&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This works really well for a long time in &lt;a href=&quot;/articles/typescript-domain-driven-design/ddd-vs-crud-design/&quot;&gt;CRUD and MVC-based applications&lt;/a&gt; without lots of business logic because we can (usually) think about them &lt;u&gt;imperatively&lt;/u&gt;. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;&lt;em&gt;This string&lt;/em&gt; maps to &lt;em&gt;this column&lt;/em&gt; in the database. I&apos;ll just do some validation &lt;em&gt;in the service&lt;/em&gt; to make sure it&apos;s not longer than 30 characters&quot;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This approach to structuring business logic is called a &quot;Transaction Script&quot; and it&apos;s the most basic one. It&apos;s defined by the absense of a &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;domain model&lt;/a&gt; and all business rules being represented with simple control statements like &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;switch&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Transaction-Scripts&quot; style=&quot;position:relative;&quot;&gt;Transaction Scripts&lt;a href=&quot;#Transaction-Scripts&quot; aria-label=&quot;Transaction Scripts permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&apos;s an example of creating a user using the Transaction Script approach.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;UserService.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; UserModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isEmailValid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TextUtils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;validateEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isFirstNameValid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TextUtils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;greaterThan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
      &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; TextUtils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lessThan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;31&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isLastNameValid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TextUtils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;greaterThan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
      &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; TextUtils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lessThan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;71&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isEmailValid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Email isn&apos;t valid&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isFirstNameValid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;First name isn&apos;t valid&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isLastNameValid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Last name isn&apos;t valid&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; UserModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What&apos;s wrong with this code? &lt;/p&gt;
&lt;p&gt;You know, it&apos;s not that bad. It works. But there &lt;em&gt;are&lt;/em&gt; a couple of important things here being ignored.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Errors aren&apos;t given the love that they deserve. We&apos;re making it hard for the calling code to be able to handle the errors possibly thrown by this block.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We&apos;re not really solving this problem, we&apos;re just putting it off for someone else to figure out how to decipher the errors later. It would be a lot easier for the next person if the errors were treated as types just like everything else in our domain.&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;There are important business rules here (constraints) that &lt;em&gt;can easily be circumvented&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In order to create a User, we need a valid &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt;, a &lt;code class=&quot;language-text&quot;&gt;firstName&lt;/code&gt; from 2-30 characters, and a &lt;code class=&quot;language-text&quot;&gt;lastName&lt;/code&gt; from 2-70 characters.&lt;/p&gt;
&lt;p&gt;What&apos;s stopping a new developer joining our team from just doing:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;bob&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;b&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;c&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;...&lt;em&gt;completely&lt;/em&gt; circumenting our efforts defining business logic (validation logic is a form of business logic).&lt;/p&gt;
&lt;p&gt;Nothing 😨.&lt;/p&gt;
&lt;p&gt;There&apos;s another problem too.&lt;/p&gt;
&lt;h2 id=&quot;Duplicating-business-rules&quot; style=&quot;position:relative;&quot;&gt;Duplicating business rules&lt;a href=&quot;#Duplicating-business-rules&quot; aria-label=&quot;Duplicating business rules permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It&apos;s nice that we&apos;re at least trying to prevent against violations to the upper and lower bound lengths for the &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt;s, but what happens when we create the &lt;code class=&quot;language-text&quot;&gt;updateUser&lt;/code&gt; method in our &lt;code class=&quot;language-text&quot;&gt;UserService&lt;/code&gt;? How much of that &lt;em&gt;constraint logic&lt;/em&gt; do we have to duplicate?&lt;/p&gt;
&lt;p&gt;All of it.&lt;/p&gt;
&lt;p&gt;And what if the business rules changed a little bit? &lt;/p&gt;
&lt;p&gt;What if, in order to create a user, you need to have &lt;strong&gt;either&lt;/strong&gt; an &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt; + &lt;code class=&quot;language-text&quot;&gt;firstName&lt;/code&gt; OR &lt;code class=&quot;language-text&quot;&gt;firstName&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;lastName&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;That would make the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; creation logic a little bit more complex, and we&apos;d have to repeat it anywhere that we create users in our code. &lt;/p&gt;
&lt;p&gt;That&apos;s a textbook &lt;a href=&quot;/wiki/anemic-domain-model/&quot;&gt;anemic domain model&lt;/a&gt;. Not &lt;em&gt;usually&lt;/em&gt; fun for web development (though, see &lt;a href=&quot;https://en.wikipedia.org/wiki/Entity_component_system&quot;&gt;Entity Component Systems&lt;/a&gt; for times it &lt;em&gt;is&lt;/em&gt; fun).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This sucks. What should we do?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;Make-illegal-states-unrepresentable&quot; style=&quot;position:relative;&quot;&gt;Make illegal states unrepresentable&lt;a href=&quot;#Make-illegal-states-unrepresentable&quot; aria-label=&quot;Make illegal states unrepresentable permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Earlier this year, functional programming &lt;em&gt;fanatic&lt;/em&gt; &lt;a href=&quot;https://twitter.com/jdegoes&quot;&gt;John A De Goes&lt;/a&gt; blasted out a tweet:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Making illegal states unrepresentable is all about statically proving that all runtime values (without exception) correspond to valid objects in the business domain. The effect of this technique on eliminating meaningless runtime states is astounding and cannot be overstated.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;— John A De Goes (@jdegoes) &lt;a href=&quot;https://twitter.com/jdegoes/status/1089949149628375040?lang=en&quot;&gt;January 28, 2019&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is an awesome quote. In programming (and science), it&apos;s often impossible to prove that something is &lt;em&gt;correct&lt;/em&gt;, but it&apos;s reasonable to prove that something is &lt;em&gt;correct enough&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;With types, we can achieve that &lt;em&gt;correct enough&lt;/em&gt;, and that makes our code much easier to reason about. And that gives us confidence to know that our business rules are being respected.&lt;/p&gt;
&lt;p&gt;This builds trust. This means potentially less unit tests against the business logic, and more tests with various inputs to the system. This makes it safer to refactor code. This enables us to continue to push forward the design. This means that the types serve as a form of documentation to the system. This reduces the amount of supplementary documentation necessary. This enables new developers to onboard faster. This makes us happier.&lt;/p&gt;
&lt;p&gt;This also happens to be the core of &lt;a href=&quot;/articles/typescript-domain-driven-design/domain-modeling-made-functional/&quot;&gt;what Scott Wlaschin teaches with his book, blog, and talks on functional domain modeling&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let&apos;s recap some approaches that we&apos;ve already covered in detail on the blog, and look at a few alternative approaches as well.&lt;/p&gt;
&lt;h2 id=&quot;Wrapping-primitives-with-domain-specific-types-to-express-a-common-language-and-prevent-misuse&quot; style=&quot;position:relative;&quot;&gt;Wrapping primitives with domain specific types to express a common language and prevent misuse&lt;a href=&quot;#Wrapping-primitives-with-domain-specific-types-to-express-a-common-language-and-prevent-misuse&quot; aria-label=&quot;Wrapping primitives with domain specific types to express a common language and prevent misuse permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The essence of DDD is to build a shared understanding of the domain with stakeholders, non-technical folk, and technical folk, and then codify that.&lt;/p&gt;
&lt;p&gt;Using types, non-techncial stakeholders can understand our code.&lt;/p&gt;
&lt;p&gt;Like this.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;forum/domain/types.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// UserName is from a separate subdomain, `Users`&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../users/domain/types&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; MemberId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Member &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; MemberId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserName
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Text &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Link &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; PostTitle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; PostId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Post &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  postId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostId
  postedBy&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Member&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostTitle&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  content&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Text &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Link&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Upvote &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  postId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  memberId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; MemberId
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Downvote &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  postId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  memberId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; MemberId
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You probably have a good idea about the type of domain that we&apos;re dealing with simply by looking at the names of the types and their relationships.&lt;/p&gt;
&lt;p&gt;Using classes (because of its &lt;a href=&quot;https://en.wikipedia.org/wiki/Nominal_type_system&quot;&gt;nominal typing&lt;/a&gt;) yields a benefit (that I haven&apos;t yet been able to get working with purely functional types in TypeScript): &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Forcing strictly nominal type checks (based on the name)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For example, even though &lt;code class=&quot;language-text&quot;&gt;PostId&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;PostTitle&lt;/code&gt; might just be &lt;em&gt;wrappers&lt;/em&gt; to a &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; value,  like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostIdProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Value is protected &lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostIdProps&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// There is only a getter, because it should never be able to change&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostTitleProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostTitle&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Also protected&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostTitleProps&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;// Also only needs a getter&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We &lt;em&gt;can&apos;t&lt;/em&gt; just substitute them in for each other.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostSlug&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// We need a PostTitle to create a PostSlug&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;postTitle&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostTitle&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PostSlug&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; postId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; PostId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; postSlug&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostSlug &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; PostSlug&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;postId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Error&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can also think of this as a way to &lt;u&gt;encode business requirements&lt;/u&gt;. If the &lt;em&gt;only&lt;/em&gt; way to create a &lt;code class=&quot;language-text&quot;&gt;PostSlug&lt;/code&gt; is to first create a &lt;code class=&quot;language-text&quot;&gt;PostTitle&lt;/code&gt;, then we&apos;re forced to first locate the factory that creates &lt;code class=&quot;language-text&quot;&gt;PostTitle&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;Think of the amount of illegal states we prevented by wrapping primitives in domain-specific types.&lt;/p&gt;
&lt;h3 id=&quot;Using-public-setters-sparingly&quot; style=&quot;position:relative;&quot;&gt;Using public setters sparingly&lt;a href=&quot;#Using-public-setters-sparingly&quot; aria-label=&quot;Using public setters sparingly permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It&apos;s easy to add getters and setters for all of the properties of a class, but &lt;em&gt;should we&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;Consider modeling a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; entity with a public &lt;code class=&quot;language-text&quot;&gt;UserId&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Entity&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;userId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserId &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Should we also add a setter?&lt;/p&gt;
&lt;p&gt;That depends on if doing so is &lt;u&gt;valid to the domain&lt;/u&gt;. &lt;/p&gt;
&lt;p&gt;From a Users, Identity &amp;#x26; Access Management context, there&apos;s no reason why the &lt;code class=&quot;language-text&quot;&gt;UserId&lt;/code&gt; should ever change to a new value. Doing so would break the relationships between &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; and any other subdomains that have a 1-to-1 relationship with &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; like &lt;code class=&quot;language-text&quot;&gt;Member&lt;/code&gt; from the Forum subdomain in  &lt;a href=&quot;https://github.com/stemmlerjs/ddd-forum&quot;&gt;DDDForum.com&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;So lets make it entirely impossible.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Entity&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;userId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserId &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// set userId (userId: UserId) {&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//   this.props.userId = userId;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// }&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I might even discourage the use of public setters &lt;em&gt;in general&lt;/em&gt; because of their rigid method signature. They clash with the way that we &lt;a href=&quot;/articles/typescript-domain-driven-design/updating-aggregates-in-domain-driven-design/&quot;&gt;handle updates in aggregates using DDD&lt;/a&gt; using &lt;code class=&quot;language-text&quot;&gt;Result&lt;/code&gt;s.&lt;/p&gt;
&lt;h3 id=&quot;Strictly-typing-nulls&quot; style=&quot;position:relative;&quot;&gt;Strictly typing &quot;null&quot;s&lt;a href=&quot;#Strictly-typing-nulls&quot; aria-label=&quot;Strictly typing nulls permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;What should you do in scenarios when you &quot;try to create an object and it fails&quot; or you &quot;try to retrieve an object and it&apos;s not found&quot;? How do you represent that?&lt;/p&gt;
&lt;p&gt;Those are pretty realistic scenarios to run into, and &lt;em&gt;passing null&lt;/em&gt; is a common practice, though not a very good one.&lt;/p&gt;
&lt;p&gt;Nulls aren&apos;t nice because to the client, they masquerade 🎭 as if they&apos;re actually the object(s) you&apos;re looking for, but as soon as you call a method or try to access a property on them, they throw errors.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; votes&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Votes&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;vote1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; vote2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; vote3&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; vote &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; votes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// throws error on the last element&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;This vote was cast by &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;vote&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;member&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;memberId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Undefined and null-y values are things that we should be prepared to deal with.&lt;/p&gt;
&lt;p&gt;In Scott Wlaschin&apos;s talk, &quot;&lt;a href=&quot;https://www.youtube.com/embed/PLFl95c-IiU&quot;&gt;Domain Modeling Made Functional&lt;/a&gt;&quot;, he suggests representing &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt; with its own type, like &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Nothing &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using this type, we can create &lt;em&gt;optional&lt;/em&gt; types using &lt;strong&gt;unions&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; SomeString &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OptionalString &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; 
  SomeString &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  Nothing&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; SomeNumber &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OptionalNumber &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; 
  SomeNumber &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  Nothing&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or we can make it generic in order to strictly represent &lt;em&gt;any&lt;/em&gt; type that may or may not have a value.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Option&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Nothing&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OptionalString &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Option&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OptionalNumber &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Option&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Building on that, the type for a Factory Function could adequately &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Email &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createEmail&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Option&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Email&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;contains&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;@&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Nothing
    &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; email &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This particular functional design pattern used to represent types that may or may not exist is called a &lt;a href=&quot;https://en.wikipedia.org/wiki/Monad_(functional_programming)&quot;&gt;monad&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When we model &lt;em&gt;nothingness&lt;/em&gt; as a type in our domain instead of just passing null, it forces any client code that relies on it to &lt;strong&gt;accomodate the possibility of nothingness&lt;/strong&gt;. &lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;I wrote an article describing how to use the &lt;i&gt;Result&lt;/i&gt; monad to model nothingness and wrap failure states with error messages. Check it out, it&apos;s called &quot;&lt;a href=&quot;/articles/enterprise-typescript-nodejs/handling-errors-result-class/&quot;&gt;Flexible Error Handling w/ the Result Class | Enterprise Node.js + TypeScript&lt;/a&gt;&quot;.&lt;/p&gt;
&lt;h3 id=&quot;Enforcing-object-creation-constraints-with-factories&quot; style=&quot;position:relative;&quot;&gt;Enforcing object creation constraints with factories&lt;a href=&quot;#Enforcing-object-creation-constraints-with-factories&quot; aria-label=&quot;Enforcing object creation constraints with factories permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Object constraints (in OO we refer to these as &lt;a href=&quot;/wiki/invariant/&quot;&gt;class invariants&lt;/a&gt;) are the rules that dictate size, shape, length, or the state that a particular domain object is allowed to be in, and at which point in time.&lt;/p&gt;
&lt;p&gt;Here are some constraint (invariant) examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Length constraints: &lt;code class=&quot;language-text&quot;&gt;PostText&lt;/code&gt; cannot be longer than 50 characters (overflow), and must be at least 3 characters (underflow)&lt;/li&gt;
&lt;li&gt;Pattern constraints: &lt;code class=&quot;language-text&quot;&gt;Email&lt;/code&gt; must be a valid email address based on a regex formula that we constructed.&lt;/li&gt;
&lt;li&gt;Complex constraints: &lt;code class=&quot;language-text&quot;&gt;PaidJobDetails&lt;/code&gt; cannot be less than 15 dollars an hour if the &lt;code class=&quot;language-text&quot;&gt;Job&lt;/code&gt;&apos;s &lt;code class=&quot;language-text&quot;&gt;Location&lt;/code&gt; is based in Ontario.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&apos;s important that the language we choose is able to reduce all the possible ways to create a valid domain object to &lt;strong&gt;one&lt;/strong&gt; way.&lt;/p&gt;
&lt;p&gt;We can use the &lt;strong&gt;factory pattern&lt;/strong&gt; for this.&lt;/p&gt;
&lt;p&gt;Here&apos;s a purely functional approach:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;domain/postTitle.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Nothing &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; EmailAddress &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Option&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Nothing&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; createEmailAddress&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Option&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;EmailAddress&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;email &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;@&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; email &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Email
    &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Nothing
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is great an all, but there&apos;s nothing stopping me from doing:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; EmailAddress &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;diddle.com&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is one of the things that I&apos;ve been able to enforce with classes using an Object-Oriented approach. Using &lt;strong&gt;private constructors&lt;/strong&gt; and &lt;strong&gt;static factory methods&lt;/strong&gt;, we can ensure that the only way domain objects is through the static factory.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EmailAddressProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EmailAddress&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ValueObject&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;EmailAddressProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Can&apos;t invoke with new from outside of class.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; EmailAddressProps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Only way to create an EmailAddress is through the static factory method &lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;EmailAddress&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; guardResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;againstNullOrUndefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;email&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;guardResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isFailure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;TextUtils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;validateEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;EmailAddress&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;EmailAddress&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EmailAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; email &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Handling-error-states&quot; style=&quot;position:relative;&quot;&gt;Handling error states&lt;a href=&quot;#Handling-error-states&quot; aria-label=&quot;Handling error states permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There are errors that we expect and know how to deal with, and errors that we don&apos;t expect and don&apos;t really know how to deal with.&lt;/p&gt;
&lt;p&gt;It&apos;s also true that for every &lt;strong&gt;single use case, there are &lt;em&gt;at least&lt;/em&gt; one or more possible ways that it can fail&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;So why is it that we often let error states fall through the cracks?&lt;/p&gt;
&lt;p&gt;We should strictly type them and represent them as domain concepts.&lt;/p&gt;
&lt;p&gt;For example, if we were building DDDForum.com, and we wanted to code out the &lt;code class=&quot;language-text&quot;&gt;UpvotePost&lt;/code&gt; use case, here&apos;s a namespace containing objects for all the possible ways it can fail.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/UpvotePost/UpvotePostErrors.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UseCaseError &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../../shared/core/UseCaseError&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Result &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../../shared/core/Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; UpvotePostErrors &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MemberNotFoundError&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UseCaseError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Couldn&apos;t find a member to upvote the post.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; UseCaseError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostNotFoundError&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UseCaseError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;slug&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Couldn&apos;t find a post by slug {&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;slug&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; UseCaseError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AlreadyUpvotedError&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UseCaseError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;postId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; memberId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;This post was already upvoted postId {&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;postId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;}, memberId {&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;memberId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; UseCaseError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For that &lt;em&gt;single&lt;/em&gt; use case, there are at least three ways that it can fail.&lt;/p&gt;
&lt;p&gt;Using the &lt;code class=&quot;language-text&quot;&gt;Either&amp;lt;T, U&amp;gt;&lt;/code&gt; monad, we can take a step up from the basic &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt; class that we learned about &lt;a href=&quot;/articles/enterprise-typescript-nodejs/handling-errors-result-class/&quot;&gt;here&lt;/a&gt;, and we can &lt;strong&gt;segregate all the possible failure states from the single success state&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here&apos;s what the response type for this use case might look like: &lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/UpvotePost/UpvotePostResponse.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Either&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Result &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../../shared/core/Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpvotePostErrors &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./UpvotePostErrors&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AppError &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../../shared/core/AppError&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; UpvotePostResponse &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Failures&lt;/span&gt;
  UpvotePostErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;MemberNotFoundError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  UpvotePostErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AlreadyUpvotedError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  UpvotePostErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PostNotFoundError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  AppError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UnexpectedError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Success&lt;/span&gt;
  Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Note:&lt;/b&gt; If you haven&apos;t already read it, check out &quot;&lt;a href=&quot;/articles/enterprise-typescript-nodejs/functional-error-handling/&quot;&gt;Functional Error Handling with Express.js and DDD | Enterprise Node.js + TypeScript&lt;/a&gt;&quot; to learn how to stop &lt;u&gt;throwing errors&lt;/u&gt; and prefer a functional approach to expressing error states.&lt;/p&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The main takeaways here are to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use Factories and &lt;a href=&quot;/blogs/typescript/static-factory-method/&quot;&gt;Factory Methods&lt;/a&gt; to prevent from repeating validation logic. Encapsulate it in one place. When the creation rules change, you only need to update code in one place. See this article on &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;Value Objects&lt;/a&gt; for how to implement this.&lt;/li&gt;
&lt;li&gt;Make it impossible for you to create domain objects without going through the factory. Use private constructors to prevent the use of the &lt;code class=&quot;language-text&quot;&gt;new&lt;/code&gt; keyword.&lt;/li&gt;
&lt;li&gt;Wrap primitives with their own domain specific classes in order to make the language more expressive, encode business requirements, and protect their internal values from change operations that don&apos;t make sense to the domain.&lt;/li&gt;
&lt;li&gt;Prefer update methods over public setters to encapsulate &lt;em&gt;change&lt;/em&gt; rules within the entity itself. Make it impossible to change things when they shouldn&apos;t be changed. &lt;/li&gt;
&lt;li&gt;Strictly type errors, nulls, and nothingness in order to remove the guesswork from client side code. They should always be able to accomodate for when something failed or was not found through static typing.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Types are law&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Types are the laws that dictate what&apos;s allowed to happen in our domain. Next time you write some code, think not only about what it would take to make the code &lt;em&gt;work&lt;/em&gt;, but also think about what could be done using types (and any language features) to prevent anyone else from putting the system in a state invalid to the domain. If you&apos;re using vanilla JavaScript, consider the challenges of preventing team members from doing invalid things, and &lt;a href=&quot;/articles/when-to-use-typescript-guide/&quot;&gt;consider if TypeScript would improve the &lt;em&gt;bylaws&lt;/em&gt; of your codebase&lt;/a&gt;. &lt;/p&gt;
&lt;h2 id=&quot;References--resources&quot; style=&quot;position:relative;&quot;&gt;References &amp;#x26; resources&lt;a href=&quot;#References--resources&quot; aria-label=&quot;References  resources permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For a purely functional introduction to how to implement your domain layer code functionally, watch Scott&apos;s &quot;&lt;a href=&quot;https://www.youtube.com/embed/PLFl95c-IiU&quot;&gt;Domain Modeling Made Functional&lt;/a&gt;&quot; talk. I recommend you check it out. It&apos;s well worth your time.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Static Factory Methods | Object-Oriented Programming w/ TypeScript]]></title><description><![CDATA[Go read "When to Use a Private Constructor | Object-Oriented Programming w/ TypeScript". You'll use static factory methods for the same…]]></description><link>https://khalilstemmler.com/blogs/typescript/static-factory-method/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/typescript/static-factory-method/</guid><pubDate>Thu, 21 Nov 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Go read &lt;a href=&quot;/blogs/typescript/when-to-use-a-private-constructor/&quot;&gt;&quot;When to Use a Private Constructor | Object-Oriented Programming w/ TypeScript&quot;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You&apos;ll use static factory methods for the &lt;u&gt;same reason&lt;/u&gt; you&apos;ll want to use a &lt;code class=&quot;language-text&quot;&gt;private&lt;/code&gt; constructor.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[When to Use a Private Constructor | TypeScript OOP]]></title><description><![CDATA[One of the first things we learn when we start out is how to create instances of objects. Typically, we do this with the  keyword. The…]]></description><link>https://khalilstemmler.com/blogs/typescript/when-to-use-a-private-constructor/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/typescript/when-to-use-a-private-constructor/</guid><pubDate>Thu, 21 Nov 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;One of the first things we learn when we start out is how to create &lt;strong&gt;instances&lt;/strong&gt; of objects. Typically, we do this with the &lt;code class=&quot;language-text&quot;&gt;new&lt;/code&gt; keyword.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Khalil Stemmler&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The actual thing that does the &lt;em&gt;creating&lt;/em&gt; is the constructor- and by default, it&apos;s public.&lt;/p&gt;
&lt;p&gt;Have you ever seen a &lt;code class=&quot;language-text&quot;&gt;private&lt;/code&gt; constructor? Changing the scope of a constructor to &lt;code class=&quot;language-text&quot;&gt;private&lt;/code&gt; removes our ability to use the &lt;code class=&quot;language-text&quot;&gt;new&lt;/code&gt; keyword.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Khalil Stemmler&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// Error&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Why on Earth would you want to do that? We can&apos;t create instances anymore. How are we supposed to get &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt; out of this &lt;code class=&quot;language-text&quot;&gt;class&lt;/code&gt; now?&lt;/p&gt;
&lt;p&gt;All is not lost, and it turns out that there is a very good reason for why you&apos;d want to do this kind of thing.&lt;/p&gt;
&lt;p&gt;In essence, it&apos;s &lt;u&gt;to enforce object creation rules&lt;/u&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Using-the-new-keyword&quot; style=&quot;position:relative;&quot;&gt;Using the new keyword&lt;a href=&quot;#Using-the-new-keyword&quot; aria-label=&quot;Using the new keyword permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When we use the &lt;code class=&quot;language-text&quot;&gt;new&lt;/code&gt; keyword, there&apos;s not really an elegant way to prevent a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; from being created if certain validation rules don&apos;t pass.&lt;/p&gt;
&lt;p&gt;We can &lt;em&gt;throw errors&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;  &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Ya need to include a name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// undefined&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But honestly, who wants to live in a world where we can&apos;t trust that a simple &lt;code class=&quot;language-text&quot;&gt;new&lt;/code&gt; statement won&apos;t throw errors. I don&apos;t feel like adopting trust issues with my codebase. &lt;/p&gt;
&lt;p&gt;We&apos;ve talked about why throwing errors is &lt;em&gt;not great&lt;/em&gt; in the &quot;&lt;a href=&quot;/articles/enterprise-typescript-nodejs/functional-error-handling/&quot;&gt;Functional Error Handling&lt;/a&gt;&quot; article, so let&apos;s think of a better way to prevent bad objects from being created.&lt;/p&gt;
&lt;h2 id=&quot;Static-factory-methods&quot; style=&quot;position:relative;&quot;&gt;Static factory methods&lt;a href=&quot;#Static-factory-methods&quot; aria-label=&quot;Static factory methods permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The best way to enforce validation logic against a domain object is to keep the constructor &lt;code class=&quot;language-text&quot;&gt;private&lt;/code&gt; and use a &lt;strong&gt;static factory method&lt;/strong&gt; to enforce the constraints.&lt;/p&gt;
&lt;p&gt;Using the &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt; class from &quot;&lt;a href=&quot;/articles/enterprise-typescript-nodejs/handling-errors-result-class/&quot;&gt;Flexible Error Handling w/ the Result Class | Enterprise Node.js + TypeScript&lt;/a&gt;&quot;, we can statically represent a success or a failure.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; guardResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;againstNullOrUndefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isAppropriateLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TextUtils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAtLeast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
      &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; TextUtils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAtMost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;31&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Fail with reason&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;guardResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;success&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;guardResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Fail with reason&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isAppropriateLength&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Must be between 2 and 31 characters&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Static method can access the constructor&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, object creation looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; userOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Khalil Stemmler&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Feel free to get even more functional with these different types of errors as well. We can statically type a &lt;code class=&quot;language-text&quot;&gt;NullValue&lt;/code&gt; error and an &lt;code class=&quot;language-text&quot;&gt;InvalidLength&lt;/code&gt; error.&lt;/p&gt;
&lt;p&gt;Using the &lt;code class=&quot;language-text&quot;&gt;Either&amp;lt;T, U&amp;gt;&lt;/code&gt; monad from &lt;a href=&quot;/articles/enterprise-typescript-nodejs/functional-error-handling/&quot;&gt;&quot;Functional Error Handling with Express.js and DDD | Enterprise Node.js + TypeScript&quot;&lt;/a&gt;, we can build return types like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; UserResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Failure types&lt;/span&gt;
  UserErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;NullValuesError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  UserErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InvalidFieldLengthError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Success type&lt;/span&gt;
  User
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[I'm Learning Everything GraphQL in 2020]]></title><description><![CDATA[If you've been writing code for at least 15 minutes, you've probably realized that the  ability to learn is one of the most important skills…]]></description><link>https://khalilstemmler.com/articles/graphql/learning-graphql-in-2020/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/graphql/learning-graphql-in-2020/</guid><pubDate>Tue, 19 Nov 2019 22:04:10 GMT</pubDate><content:encoded>&lt;p&gt;If you&apos;ve been writing code for at least 15 minutes, you&apos;ve probably realized that the  ability to learn is one of the most important skills you can possess as a developer. &lt;/p&gt;
&lt;p&gt;Things change &lt;em&gt;super quickly&lt;/em&gt; in our industry. &lt;/p&gt;
&lt;p&gt;For example, I heard about this thing called GraphQL a couple of years ago when I built my first GatsbyJS site, I blinked (maybe two or three times), realized it was everywhere, and witnessed my friends building front-end applications faster than me (and apparently having more fun doing it as well).&lt;/p&gt;
&lt;p&gt;This year, I joined &lt;a href=&quot;https://www.apollographql.com/&quot;&gt;Apollo&lt;/a&gt;, the company that builds the best tools for GraphQL developers, as a Developer Advocate. &lt;/p&gt;
&lt;p&gt;I&apos;m really excited about it because I&apos;ve &lt;em&gt;already&lt;/em&gt; been having a lot of fun creating helpful content on advanced TypeScript and Node.js for y&apos;all over the past year. &lt;/p&gt;
&lt;p&gt;To me, helping you learn and improve your skills is &lt;u&gt;the most fulfilling and meaningful  work I&apos;ve ever done&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;As an Apollo Developer Advocate, I&apos;ll be able to spend a lot more time interacting with community by creating apps, contributing to open source Apollo projects, making videos, blog posts, meeting with you in person and online in addition to rallying for you and being a direct line to our Apollo team.&lt;/p&gt;
&lt;p&gt;That being said, I have a lot to learn. &lt;/p&gt;
&lt;p&gt;I&apos;m pretty much an Apollo noob. So this should be a TON of fun.&lt;/p&gt;
&lt;h2 id=&quot;Defining-success&quot; style=&quot;position:relative;&quot;&gt;Defining success&lt;a href=&quot;#Defining-success&quot; aria-label=&quot;Defining success permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The first thing I always do whenever I start learning something new is to define what success looks like. After that, I work backwards.&lt;/p&gt;
&lt;p&gt;What would I like to be able to comfortably do? What do I want to know?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Minimize the total number of unknown unknowns about GraphQL and the developer ecosystem.&lt;/li&gt;
&lt;li&gt;Understand the timeline of major events related to GraphQL, tooling, trends, and adoption.&lt;/li&gt;
&lt;li&gt;Identify the major players in the GraphQL universe.&lt;/li&gt;
&lt;li&gt;Learn the Apollo platform and know it like the back of my hand.&lt;/li&gt;
&lt;li&gt;Understand the biggest pain points for developers using GraphQL today.&lt;/li&gt;
&lt;li&gt;Understand the current trends and where GraphQL is going in the future.&lt;/li&gt;
&lt;li&gt;Learn best practices in the following categories: &lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/federation/introduction/&quot;&gt;Federation&lt;/a&gt;, Running GraphQL in Production (&lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/&quot;&gt;Apollo Server&lt;/a&gt;, Caching, Architecture), GraphQL Development Tools (Graph Manager), Apollo Client, Schema Design.&lt;/li&gt;
&lt;li&gt;Develop my own opinions on GraphQL project architectures and when is the most and least appropriate times to develop products with it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;What-would-I-like-to-build&quot; style=&quot;position:relative;&quot;&gt;What would I like to build?&lt;a href=&quot;#What-would-I-like-to-build&quot; aria-label=&quot;What would I like to build permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When learning new programming concepts, I like to dive in by getting my hands dirty building real world applications with it. &lt;/p&gt;
&lt;p&gt;I really like this approach because it forces me to run into errors and problems that you don&apos;t get simply watching videos or reading books, and debugging is where I have some of my biggest mental breakthroughs.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Several smaller React (with Hooks) + Apollo applications in order to try out tooling (something fun and music-related).&lt;/li&gt;
&lt;li&gt;Incrementally migrate a large RESTful project to Apollo GraphQL. Perhaps &lt;a href=&quot;https://github.com/stemmlerjs/ddd-forum&quot;&gt;DDDForum.com&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Build an ambitious Domain-Driven Design-based GraphQL project with React, TypeScript, MySQL, and Sequelize using &lt;a href=&quot;https://www.apollographql.com/docs/apollo-server/federation/introduction/&quot;&gt;Apollo Federation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Deploy large and small GraphQL applications on various platforms like Heroku, AWS Lambda, Zeit Now, and Netlify.&lt;/li&gt;
&lt;li&gt;Try out different architectures, like Serverless GraphQL.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;What-would-I-like-to-teachwrite-about&quot; style=&quot;position:relative;&quot;&gt;What would I like to teach/write about?&lt;a href=&quot;#What-would-I-like-to-teachwrite-about&quot; aria-label=&quot;What would I like to teachwrite about permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The last part of my learning is usually to teach it to someone else. If I can&apos;t comfortably explain it to a friend or write about it in a blog post, I probably don&apos;t know it well enough yet. That&apos;s how I like to force myself to retain concepts- by testing that I can teach it.&lt;/p&gt;
&lt;p&gt;I&apos;d love to write/speak/train about the following &lt;em&gt;running list&lt;/em&gt; of topics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Best practices towards Enterprise GraphQL Architectures (Apollo GraphQL, Federation, Caching, and CQRS)&lt;/li&gt;
&lt;li&gt;Serverless GraphQL&lt;/li&gt;
&lt;li&gt;Comparisons between DDD and GraphQL&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Choosing-Learning-Resources&quot; style=&quot;position:relative;&quot;&gt;Choosing Learning Resources&lt;a href=&quot;#Choosing-Learning-Resources&quot; aria-label=&quot;Choosing Learning Resources permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In order to learn, I just pick a couple of resources that will be enough to get me started, and then piece things together by Googling when I get stuck. Here&apos;s where I&apos;m thinking of starting.&lt;/p&gt;
&lt;h3 id=&quot;Learning-GraphQL-Declarative-Data-Fetching-for-Modern-Web-Apps&quot; style=&quot;position:relative;&quot;&gt;Learning GraphQL: Declarative Data Fetching for Modern Web Apps&lt;a href=&quot;#Learning-GraphQL-Declarative-Data-Fetching-for-Modern-Web-Apps&quot; aria-label=&quot;Learning GraphQL Declarative Data Fetching for Modern Web Apps permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.com/Learning-GraphQL-Declarative-Fetching-Modern/dp/1492030716&quot;&gt;This book&lt;/a&gt; by &lt;a href=&quot;https://twitter.com/eveporcello?lang=en&quot;&gt;Eve Porcello&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/moontahoe?lang=en&quot;&gt;Alex Banks&lt;/a&gt; was recently recommended to me by my peers. Looks like a good starting point.&lt;/p&gt;
&lt;h3 id=&quot;Apollo-Fullstack-Tutorial&quot; style=&quot;position:relative;&quot;&gt;Apollo Fullstack Tutorial&lt;a href=&quot;#Apollo-Fullstack-Tutorial&quot; aria-label=&quot;Apollo Fullstack Tutorial permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Apollo has a pretty cool &lt;a href=&quot;https://www.apollographql.com/docs/tutorial/introduction&quot;&gt;full stack tutorial&lt;/a&gt; that I plan on walking through to get familiar with how devs are building apps on the Apollo platform.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;I&apos;m also planning on helping migrate this to TypeScript :)&lt;/p&gt;
&lt;h3 id=&quot;Principled-GraphQL&quot; style=&quot;position:relative;&quot;&gt;Principled GraphQL&lt;a href=&quot;#Principled-GraphQL&quot; aria-label=&quot;Principled GraphQL permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You know me. I like a set build a set of principles early on to decide if I&apos;m going the direction that I believe I should be with my code.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://principledgraphql.com/&quot;&gt;Principled GraphQL&lt;/a&gt; is a neat little resource of principles on GraphQL usage.&lt;/p&gt;
&lt;h3 id=&quot;Shopifys-GraphQL-Design-Guide&quot; style=&quot;position:relative;&quot;&gt;Shopify&apos;s GraphQL Design Guide&lt;a href=&quot;#Shopifys-GraphQL-Design-Guide&quot; aria-label=&quot;Shopifys GraphQL Design Guide permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&apos;m also planning on checking this one out. It seems to be a bit more low-level than Principled GraphQL, and it was recommended to me by a community member at &lt;a href=&quot;https://blog.apollographql.com/what-i-learned-at-graphql-summit-f61d6fc6680a&quot;&gt;GraphQL Summit 2019&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Read Shopify&apos;s &lt;a href=&quot;https://github.com/Shopify/graphql-design-tutorial/blob/master/TUTORIAL.md&quot;&gt;GraphQL API Design Guide&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;More-free-and-paid-stuff&quot; style=&quot;position:relative;&quot;&gt;More free and paid stuff?&lt;a href=&quot;#More-free-and-paid-stuff&quot; aria-label=&quot;More free and paid stuff permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I recently asked Twitter to help me identify the best free and paid resources.&lt;/p&gt;
&lt;p&gt;If I need anything else, I&apos;ll go to this thread :) &lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-dnt=&quot;true&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;What are the best free and paid resources to learn GraphQL?&lt;br&gt;&lt;br&gt;Link courses, books, guides + tag authors, instructors &amp;amp; devs.&lt;/p&gt;&amp;mdash; Khalil Stemmler (@khalilstemmler) &lt;a href=&quot;https://twitter.com/khalilstemmler/status/1190728052818481160?ref_src=twsrc%5Etfw&quot;&gt;November 2, 2019&lt;/a&gt;&lt;/blockquote&gt;


&lt;p&gt;Should be fun!&lt;/p&gt;
&lt;p&gt;Stay tuned for more content and subscribe to &lt;a href=&quot;/newsletter&quot;&gt;the newsletter&lt;/a&gt; if you want to get notifed when new stuff drops 🎤.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to Handle Updates on Aggregates - Domain-Driven Design w/ TypeScript]]></title><description><![CDATA[Also from the Domain-Driven Design with TypeScript series. Introduction A blog reader recently asked, "Please suggest to me the best…]]></description><link>https://khalilstemmler.com/articles/typescript-domain-driven-design/updating-aggregates-in-domain-driven-design/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/typescript-domain-driven-design/updating-aggregates-in-domain-driven-design/</guid><pubDate>Mon, 18 Nov 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;course-cta&quot;&gt;
We cover this topic in &lt;a href=&quot;https://www.essentialist.dev/master-the-essentials-of-software-design-with-typescript&quot;&gt;The Software Essentialist&lt;/a&gt; online course. Check it out if you liked this post.
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Also from the &lt;strong&gt;&lt;a href=&quot;/articles/categories/domain-driven-design/&quot;&gt;Domain-Driven Design with TypeScript&lt;/a&gt;&lt;/strong&gt; series&lt;/em&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;Introduction&quot; style=&quot;position:relative;&quot;&gt;Introduction&lt;a href=&quot;#Introduction&quot; aria-label=&quot;Introduction permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A blog reader recently asked,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Please suggest to me the best practices to deal with situations where a single field or only a few fields are present for an update against an &lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;aggregate&lt;/a&gt;&quot;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ah yes. Updates.&lt;/p&gt;
&lt;p&gt;It&apos;s inevitable you&apos;ll want to perform update &lt;a href=&quot;/articles/oop-design-principles/command-query-segregation/&quot;&gt;commands&lt;/a&gt; in a &lt;a href=&quot;/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;CRUD + MVC&lt;/a&gt; or DDD-based application. Everyone has their own way to handle updates in basic MVC applications, but it&apos;s not abundantly clear how to design updates against aggregates using DDD.&lt;/p&gt;
&lt;p&gt;In the code sample, they had a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; aggregate, which looked more or less like this:&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Note&lt;/b&gt;: I&apos;ve left comments for improvements that I recommend based on patterns we&apos;ve explored on this site in previous articles.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;domain/user.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// The user props.&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// I would recommend extracting these to props like in the&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// &quot;Understanding Domain Entities&quot; guide.&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// The way it is currently, getters and setters are exposed&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// for everything, and that&apos;s not very &quot;Intention Revealing&quot;.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Also makes it hard to restrict invalid operations (like &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// manually changing the id) and makes it hard to enforce&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// model invariants like ensuring the Phone is a valid &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// value object instance (can currently assign to null).&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Let&apos;s take full advantage of the language capabilities.&lt;/span&gt;

  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  phone&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Phone&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  address&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Address&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; phone&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// setting values here, I think&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Very good, there&apos;s a public factory method. Should type these  &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// props as their own interface UserProps {} though.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// There should be a Guard class here to ensure all props are valid.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;props &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;// This is what&apos;s new. We&apos;ll talk about this.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;props &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There&apos;s definitely ways we could improve &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; aggregate, but the real pain points are felt from within the &lt;code class=&quot;language-text&quot;&gt;UsersService&lt;/code&gt;&apos;s &lt;code class=&quot;language-text&quot;&gt;updatePhone&lt;/code&gt; method (which is something that I would normally advocate for representing as an &lt;a href=&quot;/articles/software-design-architecture/organizing-app-logic/&quot;&gt;application layer&lt;/a&gt; &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use case&lt;/a&gt;) instead.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;usersService.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;updatePhone&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;updatePhoneDto&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userEntity &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepository&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;updatePhNoDto&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; updatePhNoDto&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      phone&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Phone&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;phone&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      address&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Address&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    userRepository&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updateUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userModel&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The primary drawback to address in this code is the fact that the &lt;code class=&quot;language-text&quot;&gt;updatePhoneDto&lt;/code&gt; probably has a shape like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdatePhoneDto&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  phone&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  address&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And with all of those optional fields, we need to be able to &quot;deal with situations where a single field or only a few fields are present for an update&quot;.&lt;/p&gt;
&lt;p&gt;If &lt;u&gt;any of either&lt;/u&gt; &lt;code class=&quot;language-text&quot;&gt;phone&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt;, or &lt;code class=&quot;language-text&quot;&gt;address&lt;/code&gt; aren&apos;t present, we&apos;ll break each &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;value object&apos;s&lt;/a&gt; &lt;code class=&quot;language-text&quot;&gt;create()&lt;/code&gt; &lt;strong&gt;factory method&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That&apos;s not good.&lt;/p&gt;
&lt;h3 id=&quot;What-about-non-1-to-1-relationships&quot; style=&quot;position:relative;&quot;&gt;What about non 1-to-1 relationships?&lt;a href=&quot;#What-about-non-1-to-1-relationships&quot; aria-label=&quot;What about non 1 to 1 relationships permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We also have to consider situations where we&apos;re not just updating 1-to-1 relationships like &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;Phone&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;How do we handle updates against &lt;em&gt;1-to-many&lt;/em&gt; or &lt;em&gt;many-to-many&lt;/em&gt; relationships?&lt;/p&gt;
&lt;p&gt;For example, in &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;White Label&lt;/a&gt;, an &lt;code class=&quot;language-text&quot;&gt;Album&lt;/code&gt; can have many different &lt;code class=&quot;language-text&quot;&gt;Genre&lt;/code&gt;s assigned to it.&lt;/p&gt;
&lt;p&gt;We need some way that we can keep track or &lt;em&gt;mark&lt;/em&gt; which &lt;code class=&quot;language-text&quot;&gt;Genres&lt;/code&gt; were updated or removed in an update so that we can perform the correct persistence commands (insert? delete? update?).&lt;/p&gt;
&lt;p&gt;It can get pretty complex. And that&apos;s a necessary complexity when we use domain models to encapsulate business rules and language within code.&lt;/p&gt;
&lt;p&gt;The flow is straightforward though.&lt;/p&gt;
&lt;h3 id=&quot;Plan-of-action-for-performing-updates&quot; style=&quot;position:relative;&quot;&gt;Plan of action for performing updates&lt;a href=&quot;#Plan-of-action-for-performing-updates&quot; aria-label=&quot;Plan of action for performing updates permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Since in DDD, we usually implement the &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;Data Mapper&lt;/a&gt; pattern, the object we retrieve from persistence before we update it will be a &lt;em&gt;plain &apos;ol TypeScript object&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Our plan for performing an update against and aggregate will look like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ol&gt;
&lt;li&gt;Fetch the aggregate (simple TypeScript object) we want to change. &lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Change it.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Pass it off to a &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;repo&lt;/a&gt; to &lt;code class=&quot;language-text&quot;&gt;save()&lt;/code&gt; (or perhaps &lt;code class=&quot;language-text&quot;&gt;delete()&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;strong&gt;&lt;em&gt;challenges&lt;/em&gt; at step 2&lt;/strong&gt; are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Protecting model integrity (&lt;a href=&quot;/wiki/invariant/&quot;&gt;class invariants&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Performing validation logic&lt;/li&gt;
&lt;li&gt;Representing errors as domain concepts&lt;/li&gt;
&lt;li&gt;Keeping &quot;update code&quot; DRY&lt;/li&gt;
&lt;li&gt;Choosing the best ways to represent updates&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;strong&gt;challenges at step 3&lt;/strong&gt; are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Performing an atomic update as a single transaction &lt;/li&gt;
&lt;li&gt;Knowing whether to perform an &lt;em&gt;update&lt;/em&gt;, an &lt;em&gt;insert&lt;/em&gt; or a &lt;em&gt;delete&lt;/em&gt; based  on the changes from the domain model. &lt;/li&gt;
&lt;li&gt;Scaffolding across foreign-key tables within the &lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;aggregate boundary&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lets start with the basics.&lt;/p&gt;
&lt;p&gt;In this article, we&apos;ll cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to handle updates (update, insert, delete) within aggregates with 1-to-1 relationships&lt;/li&gt;
&lt;li&gt;How mutations to your domain model can contain class invariants that need to be represented as domain concepts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We&apos;ll go into more advanced stuff like 1-to-many relationships in another article.&lt;/p&gt;
&lt;h2 id=&quot;Prerequisites&quot; style=&quot;position:relative;&quot;&gt;Prerequisites&lt;a href=&quot;#Prerequisites&quot; aria-label=&quot;Prerequisites permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In order to get the most out of this article, there are a few things that you might want to read first.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The primary domain-driven design building blocks: &lt;a href=&quot;/articles/typescript-domain-driven-design/entities/&quot;&gt;domain entities&lt;/a&gt;, &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;value objects&lt;/a&gt;, &lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;aggregate roots&lt;/a&gt; and aggregate boundaries.&lt;/li&gt;
&lt;li&gt;How to use &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;DTOs, Repositories, and Mappers&lt;/a&gt; to persist and transform domain objects to other representations.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;/articles/oop-design-principles/command-query-segregation/&quot;&gt;Command-Query Segregation Principle&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;How every feature of an application is a &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use case&lt;/a&gt;, which is either a command or a query.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;A-basic-example-1-to-1&quot; style=&quot;position:relative;&quot;&gt;A basic example (1-to-1)&lt;a href=&quot;#A-basic-example-1-to-1&quot; aria-label=&quot;A basic example 1 to 1 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&apos;s take the example we looked at before: the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; aggregate and it&apos;s relationship to &lt;code class=&quot;language-text&quot;&gt;phone&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;address&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Creating-the-domain-model&quot; style=&quot;position:relative;&quot;&gt;Creating the domain model&lt;a href=&quot;#Creating-the-domain-model&quot; aria-label=&quot;Creating the domain model permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&apos;m going to model the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; aggregate a little differently than the example provided based on things we&apos;ve covered in the &lt;a href=&quot;/articles/categories/domain-driven-design/&quot;&gt;Domain-Driven Design w/ TypeScript series&lt;/a&gt; already.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;domain/user.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AggregateRoot &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../core/domain/AggregateRoot&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../core/domain/UniqueEntityID&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserCreated &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../events/userCreated&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Result &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../core/logic/Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./userId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Email &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./email&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Phone &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./phone&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Address &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./address&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Guard &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../core/logic/Guard&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  phone&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Phone&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  address&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Address&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Only getters so far, no way to perform changes to&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// the model after it&apos;s been created.&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;userId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserId &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; UserId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;phone&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Phone &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;phone&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Email &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Address &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// The only way to create or reconstitute a User is to use the static factory&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// method here.&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; guardResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;againstNullOrUndefinedBulk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;phone&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;phone&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;email&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;address&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;guardResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;success&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;guardResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isNewUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Dispatch a domain event if it&apos;s new. Otherwise, it&apos;s just an&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// entity being reconstituted from persistence.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isNewUser&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDomainEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserCreated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Cool, now let&apos;s talk about the &lt;strong&gt;use case&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Use-Case-setup&quot; style=&quot;position:relative;&quot;&gt;Use Case setup&lt;a href=&quot;#Use-Case-setup&quot; aria-label=&quot;Use Case setup permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We want to provide a way to update the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; aggregate, so let&apos;s start by creating a new &lt;code class=&quot;language-text&quot;&gt;UpdateUser&lt;/code&gt; use case in our use cases folder for the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; subdomain.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;modules/
  users/                &lt;span class=&quot;token comment&quot;&gt;# `users` subdomain&lt;/span&gt;
    domain/
      &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
      user.ts
    &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
    useCases/
      updateUser/
        UpdateUser.ts   &lt;span class=&quot;token comment&quot;&gt;# Use case!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;Folder structure following the Screaming Architecture / Package by Component principle.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/updateUser/UpdateUser.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUser&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// import dependencies&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// execute application layer logic&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you&apos;ve read the &lt;a href=&quot;/articles/software-design-architecture/domain-driven-design-vs-clean-architecture/&quot;&gt;Clean Architecture vs. Domain-Driven Design concepts&lt;/a&gt; article, you&apos;ll remember that the responsibility of use cases at this layer are to simply &lt;em&gt;fetch&lt;/em&gt; the domain objects we&apos;ll need to complete this operation, allow them to interact with each other (at the domain layer), and then save the transaction (by passing the affected aggregate root to it&apos;s repository).&lt;/p&gt;
&lt;p&gt;That&apos;s just what we&apos;ll do.&lt;/p&gt;
&lt;p&gt;Let&apos;s create a &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;DTO&lt;/a&gt; in order to specify the inputs to this use case.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
updateUser/
  UpdateUser.ts     &lt;span class=&quot;token comment&quot;&gt;# Use Case&lt;/span&gt;
  UpdateUserDTO.ts  &lt;span class=&quot;token comment&quot;&gt;# DTO&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/updateUser/UpdateUserDTO.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUserDto&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  phone&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  address&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we&apos;ll update our use case to use that as the input.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/updateUser/UpdateUser.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserDTO &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserDTO&apos;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUser&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// import dependencies&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// execute application layer logic&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Cool. Now let&apos;s &lt;a href=&quot;/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;dependency inject&lt;/a&gt; a &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; so that we can get access to the &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; aggregate that we want to change in this transaction, then let&apos;s get it.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/updateUser/UpdateUser.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IUserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../repos/interfaces/userRepo&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserDTO &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserDTO&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUser&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findUserById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Handle not found error. &lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Continue&lt;/span&gt;

  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I&apos;m going to hook up some &lt;a href=&quot;/articles/enterprise-typescript-nodejs/functional-error-handling/&quot;&gt;expressive error handling&lt;/a&gt; because I don&apos;t want a &quot;&lt;em&gt;Not Found&lt;/em&gt;&quot; error to go unswallowed by the consumer of this use case.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Note:&lt;/b&gt; This is how we can strictly type and express any other application-level (use case) or domain layer errors that might get returned. The primary benefit of not throwing errors but instead representing them as first-class citizens of our app is that we &lt;i&gt;force the client&lt;/i&gt; using our use case to handle the error states (that we &lt;i&gt;know for sure&lt;/i&gt; will occur at some point).&lt;/p&gt;
&lt;p&gt;Two new files.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
updateUser/
  UpdateUser.ts         &lt;span class=&quot;token comment&quot;&gt;# Use Case&lt;/span&gt;
  UpdateUserDTO.ts      &lt;span class=&quot;token comment&quot;&gt;# DTO&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  UpdateUserErrors.ts   &lt;span class=&quot;token comment&quot;&gt;# Holds all the unique types of application errors&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  UpdateUserResult.ts   &lt;span class=&quot;token comment&quot;&gt;# Express the result as a functional error type&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Lets create the namespace to represent errors for this use case.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;updateUser/UpdateUserErrors.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UseCaseError &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../../shared/core/UseCaseError&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Result &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../../shared/core/Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; UpdateUserErrors &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserNotFoundError&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UseCaseError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Couldn&apos;t find user id {&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;userId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;} to update.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; UseCaseError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then we&apos;ll create our strict return type so that clients can know what success and failure states to expect.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;updateUser/UpdateUserResult.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Either&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Result &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../../shared/core/Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpvotePostErrors &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./UpvotePostErrors&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AppError &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../../shared/core/AppError&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; UpdateUserResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
  UpdateUserErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UserNotFoundError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// Specific use case error&lt;/span&gt;
  AppError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UnexpectedError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;            &lt;span class=&quot;token comment&quot;&gt;// Global app error&lt;/span&gt;
  Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                          &lt;span class=&quot;token comment&quot;&gt;// Misc errors (value objects)&lt;/span&gt;
  Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;                          &lt;span class=&quot;token comment&quot;&gt;// Success!&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Error handling articles:&lt;/b&gt; No idea what I&apos;m doing? First read &quot;&lt;a href=&quot;/articles/enterprise-typescript-nodejs/handling-errors-result-class/&quot;&gt;Flexible Error Handling w/ the Result Class&lt;/a&gt;&quot; and then read &quot;&lt;a href=&quot;/articles/enterprise-typescript-nodejs/functional-error-handling/&quot;&gt;Functional Error Handling with Express.js and DDD&lt;/a&gt;&quot;.&lt;/p&gt;
&lt;p&gt;Then let&apos;s update the use case with the return type, represent the not found error, and represent the  &lt;code class=&quot;language-text&quot;&gt;void&lt;/code&gt; success state&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/updateUser/UpdateUser.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IUserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../repos/interfaces/userRepo&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserDTO &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserDTO&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserResult &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserResult&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserErrors &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserErrors&apos;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUser&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findUserById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUserErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UserNotFoundError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Update logic goes here&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Fantastic. We&apos;re all set up with to write some update logic now. &lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;Do you know how the Repository pattern works? Do you know how to convert an ORM model (like Sequelize or TypeORM) to a domain object (like an Aggregate Root, Entity or Value Object)? If not, check out &quot;&lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;Implementing DTOs, Mappers &amp; the Repository Pattern using the Sequelize ORM [with Examples] - DDD w/ TypeScript&lt;/a&gt;&quot;.&lt;/p&gt;
&lt;h3 id=&quot;Handling-update-logic&quot; style=&quot;position:relative;&quot;&gt;Handling update logic&lt;a href=&quot;#Handling-update-logic&quot; aria-label=&quot;Handling update logic permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In this particular scenario, we have a DTO with several keys that we&apos;d like to update: &lt;code class=&quot;language-text&quot;&gt;phone&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;address&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Depending on the domain, each of these &lt;em&gt;could possibly&lt;/em&gt; be modelled as simple &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;value objects&lt;/a&gt; because they&apos;re more complex than simple &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; types and have validation rules to dictate what a valid instance of them looks like.&lt;/p&gt;
&lt;p&gt;We can start by using each value object&apos;s factory method (which encapsulates its respective validation logic).&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/updateUser/UpdateUser.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IUserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../repos/interfaces/userRepo&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserDTO &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserDTO&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserResult &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserResult&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserErrors &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserErrors&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Phone &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../domain/phone&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Email &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../domain/email&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Address &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../domain/addres&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUser&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findUserById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUserErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UserNotFoundError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Create value object instances&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; phoneOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Phone&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Phone&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;phone&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emailOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Email&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; addressOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Address&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Address&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;/span&gt;    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The problem is that a request to this use case might &lt;em&gt;not&lt;/em&gt; contain each of the keys on the dto interface. It&apos;s likely that we only want to update &lt;code class=&quot;language-text&quot;&gt;phone&lt;/code&gt; but not also &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;address&lt;/code&gt; in a single request.&lt;/p&gt;
&lt;p&gt;We can write our own null checks or use a utility like lodash&apos;s &lt;code class=&quot;language-text&quot;&gt;has&lt;/code&gt; function. It will return &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt; if a property exists on an object.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/updateUser/UpdateUser.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IUserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../repos/interfaces/userRepo&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserDTO &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserDTO&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserResult &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserResult&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserErrors &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserErrors&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Phone &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../domain/phone&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Email &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../domain/email&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Address &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../domain/addres&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; has &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lodash&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUser&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findUserById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUserErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UserNotFoundError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;phone&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; phoneOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Phone&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Phone&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;phone&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token comment&quot;&gt;// update &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;email&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emailOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Email&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token comment&quot;&gt;// update &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;address&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; addressOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Address&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Address&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token comment&quot;&gt;// update &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Awesome. Now we won&apos;t attempt to update something that&apos;s not even included in the request. &lt;/p&gt;
&lt;p&gt;Focusing in on one of the keys (like &lt;code class=&quot;language-text&quot;&gt;phone&lt;/code&gt; for example) if we were able to successfully create the value object, we can go ahead and update &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; with it. &lt;/p&gt;
&lt;p&gt;And if we weren&apos;t able to create it, yet we included &lt;em&gt;some value&lt;/em&gt; for that key in the request, that probably means that there was a validation error that didn&apos;t pass and we should let the client know about that (matches the &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;any&amp;gt;&lt;/code&gt; error type).&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/updateUser/UpdateUser.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUser&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;phone&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; phoneOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Phone&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Phone&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;phone&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;phoneOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updatePhone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;phoneOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// This will be of Phone type.&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;phoneOrError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// This will be a Result&amp;lt;any&gt; return type.&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We have a new method on the &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; aggregate called &lt;code class=&quot;language-text&quot;&gt;updatePhone(phone: Phone)&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;domain/user.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;phone&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Phone &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;phone&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;updatePhone&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;phone&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Phone&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;phone &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; phone&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Simple enough.&lt;/p&gt;
&lt;p&gt;Here&apos;s where it gets interesting...&lt;/p&gt;
&lt;h4 id=&quot;Atomic-Transactions&quot; style=&quot;position:relative;&quot;&gt;Atomic Transactions&lt;a href=&quot;#Atomic-Transactions&quot; aria-label=&quot;Atomic Transactions permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Lets say we wanted to update &lt;code class=&quot;language-text&quot;&gt;phone&lt;/code&gt; AND &lt;code class=&quot;language-text&quot;&gt;address&lt;/code&gt; in single transaction. &lt;/p&gt;
&lt;p&gt;If &lt;code class=&quot;language-text&quot;&gt;phone&lt;/code&gt; was valid but &lt;code class=&quot;language-text&quot;&gt;address&lt;/code&gt; was &lt;strong&gt;not&lt;/strong&gt;, should we let the transaction &lt;u&gt;partially update&lt;/u&gt; the &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; aggregate or should the entire transaction fail?&lt;/p&gt;
&lt;p&gt;It should fail, correct?&lt;/p&gt;
&lt;p&gt;Things have the potential to get messy, code can get hard to debug, and things can be challenging to reason about if we were to allow partial transactions. A request to &lt;code class=&quot;language-text&quot;&gt;UPDATE&lt;/code&gt; the &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; has to be &lt;u&gt;fully correct&lt;/u&gt; for it to succeed.&lt;/p&gt;
&lt;p&gt;How do we do this?&lt;/p&gt;
&lt;p&gt;Using our trusty &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt; class and its &lt;code class=&quot;language-text&quot;&gt;combine(results: Result&amp;lt;T&amp;gt;[])&lt;/code&gt; method of  course!~&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;We want to keep track of &lt;strong&gt;all the changes&lt;/strong&gt; in a transaction, so let&apos;s add a &lt;code class=&quot;language-text&quot;&gt;changes: Result&amp;lt;T&amp;gt;[]&lt;/code&gt; property and a couple of methods to manage it as well.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/updateUser/UpdateUser.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUser&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; changes&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addChange&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getCombinedChangesResult&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;combine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The requirement now is that every time we mutate an aggregate, that needs to issue a &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Going back to our &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; aggregate, we can change the method to accomodate our design decision.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;domain/user.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;phone&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Phone &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;phone&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;updatePhone&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;phone&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Phone&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;phone &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; phone&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This might not seem like a great design decision right away. In our &lt;code class=&quot;language-text&quot;&gt;updatePhone&lt;/code&gt; method, the &lt;a href=&quot;https://en.wikipedia.org/wiki/Cyclomatic_complexity&quot;&gt;cyclomatic complexity&lt;/a&gt; hasn&apos;t really changed at all - there are the same number of code paths. So this additional complexity doesn&apos;t make a whole lot of sense upfront.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Note:&lt;/b&gt; After we finish this up, I&apos;ll show you an example of a real life aggregate that enforces class invariants that dictate &lt;i&gt;when&lt;/i&gt; and &lt;i&gt;how&lt;/i&gt; it&apos;s allowed to change. It makes much better use of the Result type.&lt;/p&gt;
&lt;p&gt;Using this pattern, we can add each mutation against the &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; aggregate to the changes array.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/updateUser/UpdateUser.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IUserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../repos/interfaces/userRepo&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserDTO &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserDTO&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserResult &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserResult&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserErrors &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserErrors&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Phone &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../domain/phone&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Email &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../domain/email&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Address &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../domain/addres&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; has &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lodash&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUser&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; changes&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addChange&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getCombinedChangesResult&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;combine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findUserById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUserErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UserNotFoundError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;phone&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; phoneOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Phone&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Phone&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;phone&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;phoneOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addChange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updatePhone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;phoneOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;phoneOrError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;email&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emailOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Email&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emailOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addChange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updateEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emailOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emailOrError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;address&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; addressOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Address&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Address&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;addressOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addChange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updateEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;addressOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;addressOrError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then at the end, if all of the changes were successful, we can pass it to the repository to be saved. &lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/updateUser/UpdateUser.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUser&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; changes&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addChange&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getCombinedChangesResult&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;combine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCombinedChangesResult&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token comment&quot;&gt;// Save!&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AppError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And the &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; knows whether to perform an &lt;code class=&quot;language-text&quot;&gt;update&lt;/code&gt; or a &lt;code class=&quot;language-text&quot;&gt;create&lt;/code&gt; because it will first check to see if the entity exists or not.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;repos/implementations/sequelizeUserRepo.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SequelizeUserRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; UserModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;BaseUser&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; exists &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;exists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rawSequelizeUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; UserMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toPersistence&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; UserModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rawSequelizeUser&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Update!&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;For more on using Repositories to persist domain entities, read &quot;&lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;Implementing DTOs, Mappers &amp; the Repository Pattern using the Sequelize ORM [with Examples]&lt;/a&gt;&quot;.&lt;/p&gt;
&lt;h3 id=&quot;Extracting-change-functionality-to-a-interface&quot; style=&quot;position:relative;&quot;&gt;Extracting &quot;change&quot; functionality to a interface&lt;a href=&quot;#Extracting-change-functionality-to-a-interface&quot; aria-label=&quot;Extracting change functionality to a interface permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Pretty much all &lt;code class=&quot;language-text&quot;&gt;update&lt;/code&gt; use cases need to use this kind of change functionality so I&apos;d recommend extracting it into it&apos;s own separate class and then using composition to add it to use cases that need it.&lt;/p&gt;
&lt;div class=&quot;special-quote solid-book-cta&quot;&gt;
  &lt;a href=&quot;https://solidbook.io&quot; class=&quot;solid-book-logo-container&quot;&gt;
    &lt;img src=&quot;/img/resources/solid-book/book-logo.png&quot;/&gt;
  &lt;/a&gt;
  &lt;p&gt;
    &lt;b&gt;Design Principle&lt;/b&gt;: &quot;Prefer composition over inheritance&quot;. - via &lt;a href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt;: The Software Architecture &amp; Design Handbook
  &lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Result &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Use cases that need changes can implement this&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;WithChanges&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  changes&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Changes&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Extracted into its own class&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Changes&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; changes&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addChange&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getCombinedChangesResult&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;combine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This changes the usage in our use case slightly:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/updateUser/UpdateUser.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IUserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../repos/interfaces/userRepo&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserDTO &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserDTO&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserResult &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserResult&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpdateUserErrors &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UpdateUserErrors&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Phone &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../domain/phone&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Email &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../domain/email&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Address &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../domain/addres&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; has &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lodash&apos;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUser&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; WithChanges &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; changes&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Changes&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Changes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UpdateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpdateUserResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findUserById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpdateUserErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UserNotFoundError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;phone&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; phoneOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Phone&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Phone&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;phone&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;phoneOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addChange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updatePhone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;phoneOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;phoneOrError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCombinedChangesResult&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Save!&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AppError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Representing-invalid-updates-that-break-class-invariants&quot; style=&quot;position:relative;&quot;&gt;Representing invalid updates that break class invariants&lt;a href=&quot;#Representing-invalid-updates-that-break-class-invariants&quot; aria-label=&quot;Representing invalid updates that break class invariants permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I said I&apos;d give you a better example of why using &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt; from within a domain entity is a good idea when we&apos;re performing mutations against it in the context of an update use case.&lt;/p&gt;
&lt;p&gt;Here&apos;s one from &lt;a href=&quot;https://github.com/stemmlerjs/ddd-forum&quot;&gt;DDDForum.com&lt;/a&gt;, the Hackernews-inspired forum app built with TypeScript &amp;#x26; DDD from solidbook.io.&lt;/p&gt;
&lt;p&gt;A &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt; can have either a &lt;code class=&quot;language-text&quot;&gt;link&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;text&lt;/code&gt;, but not both.&lt;/p&gt;
&lt;p&gt;And if you wish to change your &lt;code class=&quot;language-text&quot;&gt;link&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;text&lt;/code&gt;, you can only do so if the &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt; &lt;strong&gt;doesn&apos;t yet have any comments&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;See that? In this scenario, there are business rules that dictate when it&apos;s OK for something to change. That&apos;s the power of DDD and model-driven design. The shift that should happen in your thinking is to prefer trying to represent those invalid error states as domain concepts, rather than than throwing untyped errors.&lt;/p&gt;
&lt;p&gt;Here&apos;s a snippet from the &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt; aggregate.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;domain/post.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/** Represents the different types of things that can happen when we try 
  * to update the post text or link.
  */&lt;/span&gt; 

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; UpdatePostTextOrLinkResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;/**
   * This error means that we&apos;re trying to update a text post when the 
   * post is actually a link post, or vice versa.
   */&lt;/span&gt;
  EditPostErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InvalidPostTypeOperationError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; 
  &lt;span class=&quot;token comment&quot;&gt;/**
   * This error means that the post is sealed due to there already being
   * comments
   */&lt;/span&gt;
  EditPostErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PostSealedError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
  Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Post&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PostProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;updateText&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;postText&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostText&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UpdatePostTextOrLinkResult &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isTextPost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EditPostErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InvalidPostTypeOperationError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EditPostErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PostSealedError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; guardResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;againstNullOrUndefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;postText&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;postText&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;guardResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;succeeded&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;guardResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; postText&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;updateLink&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;postLink&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostLink&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UpdatePostTextOrLinkResult &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isLinkPost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EditPostErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InvalidPostTypeOperationError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EditPostErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PostSealedError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; guardResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;againstNullOrUndefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;postLink&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;postLink&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;guardResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;succeeded&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;guardResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;link &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; postLink&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Brutalist Web Design]]></title><description><![CDATA[Readers of khalilstemmler.com either love or hate the design of the site. When I was designing the site, I knew that I wanted to draw a…]]></description><link>https://khalilstemmler.com/blogs/thoughts/brutalist-websites/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/thoughts/brutalist-websites/</guid><pubDate>Tue, 05 Nov 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Readers of &lt;a href=&quot;https://khalilstemmler.com&quot;&gt;khalilstemmler.com&lt;/a&gt; either &lt;strong&gt;love&lt;/strong&gt; or &lt;em&gt;hate&lt;/em&gt; the design of the site. When I was designing the site, I knew that I wanted to draw a little bit of inspiration from &lt;strong&gt;brutalist web design&lt;/strong&gt;. The challenge is that most brutalist work can be very polarizing.&lt;/p&gt;
&lt;h2 id=&quot;What-is-brutalism&quot; style=&quot;position:relative;&quot;&gt;What is brutalism?&lt;a href=&quot;#What-is-brutalism&quot; aria-label=&quot;What is brutalism permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The term brutalism is derived from the French &lt;em&gt;béton brut&lt;/em&gt;, meaning “raw concrete”.&lt;/p&gt;
&lt;p&gt;Concrete brutalist buildings often &lt;u&gt;reflect back upon the forms used to make them&lt;/u&gt;. &lt;/p&gt;
&lt;p&gt;Take the following image of the &lt;a href=&quot;https://ca.phaidon.com/agenda/architecture/articles/2018/september/20/these-brutalist-buildings-look-a-bit-like-jenga-blocks/&quot;&gt;Ministry of Education in Lima, Peru&lt;/a&gt;. It&apos;s a Jenga-looking building that is unmistakeably hard to &lt;strong&gt;not&lt;/strong&gt; realize is built out of several blocks of concrete.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;/img/blog/brutalism/architecture.jpg&quot;/&gt;
&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;Ministry of Education, Lima, Peru, 2012, by DLPS&lt;/p&gt;
&lt;p&gt;Not a lot of architecture, artwork or any finished product for that matter, sets out to draw blaring attention to the tools used to create it. &lt;/p&gt;
&lt;p&gt;Here&apos;s another one in my neighboring city of Toronto. Most people don&apos;t mind working in brutalist office, but to see a home that looks like the architectural planning could have been an avid  &lt;strong&gt;Minecraft&lt;/strong&gt; player, is pretty unique. Personally, I love it. I&apos;d love to live here.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;/img/blog/brutalism/toronto-home.jpg&quot;/&gt;
&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;Brutalist home in Toronto, from &lt;a href=&quot;http://www.ontarioarchitecture.com/Brutalist.htm&quot;&gt;ontarioarchitecture.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Last one, City Hall in my hometown, &lt;a href=&quot;https://en.wikipedia.org/wiki/Brantford&quot;&gt;Brantford, Ontario&lt;/a&gt;. I remember skateboarding around here as a kid. From a young age, something drew me to this area with those interlocking rectangular shapes made from concrete, though I never quite knew why.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;/img/blog/brutalism/brantford-city-hall.jpg&quot;/&gt;
&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;City Hall in Brantford, Ontario &lt;a href=&quot;http://www.ontarioarchitecture.com/Brutalist.htm&quot;&gt;ontarioarchitecture.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Most brutalist buildings are made from &lt;strong&gt;raw concrete&lt;/strong&gt;, so it&apos;s interesting to see how &lt;em&gt;raw-ness&lt;/em&gt; applies to the web. &lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;/p&gt;
&lt;h2 id=&quot;What-is-brutalist-web-design&quot; style=&quot;position:relative;&quot;&gt;What is brutalist web design?&lt;a href=&quot;#What-is-brutalist-web-design&quot; aria-label=&quot;What is brutalist web design permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;In it&apos;s ruggedness and lack of concern to look comfortable or easy, Brutalism can be seen as a reaction by a younger generation to the lightness, optimism, and frivolity of today&apos;s web design. - &lt;a href=&quot;https://brutalistwebsites.com/&quot;&gt;brutalistwebsites.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In some ways, the recent trend of implementing brutalism in design stems back to the early days of the web. Back then, websites were brutal because &lt;u&gt;they had to be&lt;/u&gt;. In present times, going brutal is more of a way to stand out and rebel against the squeaky-clean designs that cover the web today.&lt;/p&gt;
&lt;p&gt;You know when you&apos;re looking at a brutalist website. Here are a few examples from &lt;a href=&quot;https://brutalistwebsites.com/&quot;&gt;brutalistwebsites.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/brutalism/brutalist-sites.png&quot; alt=&quot;Brutalist websites&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Several brutalist websites @ &lt;a href=&quot;https://brutalistwebsites.com/&quot;&gt;brutalistwebsites.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The experience you get from a deconstructed brutalist website is similar to the one we get when we look at buildings &lt;strong&gt;obviously made from slabs of concrete&lt;/strong&gt;. We really pay notice to the &lt;u&gt;HTML, CSS and JavaScript that came together to create it&lt;/u&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Brutalist works reflect back upon the forms used to make them&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;Brutalism-vs-convention&quot; style=&quot;position:relative;&quot;&gt;Brutalism vs. convention&lt;a href=&quot;#Brutalism-vs-convention&quot; aria-label=&quot;Brutalism vs convention permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If there&apos;s anything we&apos;ve noticed so far about the brutalist architecture and web design, it&apos;s that brutalist works often challenge the popular conventions.&lt;/p&gt;
&lt;p&gt;Let&apos;s talk about &lt;strong&gt;landing pages&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Landing-page-design&quot; style=&quot;position:relative;&quot;&gt;Landing page design&lt;a href=&quot;#Landing-page-design&quot; aria-label=&quot;Landing page design permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Effective landing page design can make or save a company lots of money. My favourite author on the internet, &lt;a href=&quot;https://www.julian.com/guide/growth/landing-pages&quot;&gt;Julian Shapiro&lt;/a&gt; has written extensive handbooks on the formula behind landing page design.&lt;/p&gt;
&lt;p&gt;Here&apos;s his diagram illustrating the formula to high-converting landing pages (used by Stripe and other big-name YC startup companies).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/brutalism/landing-page-design.png&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Effective Landing Page templates, courtesy of &lt;a href=&quot;https://www.julian.com/guide/growth/landing-pages&quot;&gt;julian.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is pretty much what we&apos;ve grown accustomed to looking at for homepages of businesses on the internet in 2019. Stripe&apos;s landing page is exemplary.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/brutalism/stripe.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;In order to make money on the internet, landing page design, copywriting, and conversion rate optization are topics you could spend a lot of time trying to master. It&apos;s also what companies in  the business of making money invest a lot of capital on.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Brutalist websites&lt;/strong&gt; however, trade in attention to today&apos;s popular conventions (such as flat-design, 3x3 cards, and minimal or geometrically pleasing backgrounds) for &lt;em&gt;raw&lt;/em&gt; and memorable web experiences.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/brutalism/brutal-site.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;While it may not be the optimal design for those attempting to selling something, because users might be less familiar with how your site handles navigation and other standard web conventions, it can either be refreshing (because it enables users to just &lt;em&gt;go along for the ride&lt;/em&gt;) or completely aggravating. &lt;/p&gt;
&lt;h3 id=&quot;Portfolio-websites-and-interactive-experiences&quot; style=&quot;position:relative;&quot;&gt;Portfolio websites and interactive experiences&lt;a href=&quot;#Portfolio-websites-and-interactive-experiences&quot; aria-label=&quot;Portfolio websites and interactive experiences permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;True brutalist websites seem to work better when they serve as porfolios for artists and designers or homepages for musicians. I think that works well because the transaction of first impression is more important and has potential to leave an impact deeper and more valuable than any monetary or business transaction. Guess it depends on who&apos;s asking.&lt;/p&gt;
&lt;p&gt;Here are a few interesting ones.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://design.byform.co/&quot;&gt;Dan Flynn&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/brutalism/dan-flynn.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.modeselektor.com&quot;&gt;modeselektor.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/brutalism/modselektor.png&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;Rules-of-Brutalist-Web-Design&quot; style=&quot;position:relative;&quot;&gt;Rules of Brutalist Web Design&lt;a href=&quot;#Rules-of-Brutalist-Web-Design&quot; aria-label=&quot;Rules of Brutalist Web Design permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Guidelines for Brutalist Web Design by &lt;a href=&quot;https://brutalist-web.design/&quot;&gt;David Bryant Copeland&lt;/a&gt; state that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Content is readable on all reasonable screens and devices.&lt;/li&gt;
&lt;li&gt;Only hyperlinks and buttons respond to clicks.&lt;/li&gt;
&lt;li&gt;Hyperlinks are underlined and buttons look like buttons.&lt;/li&gt;
&lt;li&gt;The back button works as expected.&lt;/li&gt;
&lt;li&gt;View content by scrolling.&lt;/li&gt;
&lt;li&gt;Decoration when needed and no unrelated content.&lt;/li&gt;
&lt;li&gt;Performance is a feature.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Brutalism-in-art-and-music&quot; style=&quot;position:relative;&quot;&gt;Brutalism in art and music&lt;a href=&quot;#Brutalism-in-art-and-music&quot; aria-label=&quot;Brutalism in art and music permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&apos;ve always been attracted to &lt;em&gt;raw&lt;/em&gt;-ness in art, design, and music. &lt;/p&gt;
&lt;p&gt;Personally, I&apos;m borderline obsessed with music of the late-1970s / early-80s with ties to the avante-garde &lt;a href=&quot;https://en.wikipedia.org/wiki/No_wave&quot;&gt;no wave&lt;/a&gt; scene in New York. And I&apos;m equally obsessed with the novel recording techniques and expressionist vocalisms of several English and Australian &lt;a href=&quot;https://en.wikipedia.org/wiki/Post-punk&quot;&gt;post-punk&lt;/a&gt; groups.&lt;/p&gt;
&lt;p&gt;In a similar vein to brutalism, my all-time favourite bands come from a lineage of blatant disregard for the popularly agreed-upon constructs of what music &lt;em&gt;should&lt;/em&gt; sound like. It&apos;s the type of music that reflects back upon the instruments used to create it.&lt;/p&gt;
&lt;h3 id=&quot;The-Pop-Group&quot; style=&quot;position:relative;&quot;&gt;The Pop Group&lt;a href=&quot;#The-Pop-Group&quot; aria-label=&quot;The Pop Group permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For me, it starts with &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Pop_Group&quot;&gt;The Pop Group&lt;/a&gt;, an English band formed in the peak era of post-punk. &lt;/p&gt;
&lt;p&gt;The ironically named &lt;em&gt;Pop&lt;/em&gt; Group is a discordant band writing songs where almost every instrument is independently fighting for attention, and it reflects back towards the listener.&lt;/p&gt;
&lt;p&gt;In popular music (take Madonna&apos;s &lt;em&gt;&quot;Lucky Star&quot;&lt;/em&gt;, for example), a lot of effort is focused towards making all the instruments compliment each other. In other words, a &lt;strong&gt;good pop song&lt;/strong&gt; is one you can &lt;strong&gt;dance to&lt;/strong&gt;, is free of awkward silences, and nothing quite sticks out at you awkwardly.&lt;/p&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;350px&quot; src=&quot;https://www.youtube.com/embed/ThHz9wlBeLU&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p class=&quot;caption&quot;&gt;Madonna&apos;s &quot;Lucky Star&quot;. An excellent pop song.&lt;/p&gt;
&lt;p&gt;On &lt;em&gt;&quot;Lucky Star&quot;&lt;/em&gt;, there are several instruments in the mix strategically placed and equalized to sweeten the resulting pop song. Sure, there&apos;s a lot going on, but &lt;em&gt;none of it is discordant&lt;/em&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;[Madonna] was [initially] unhappy with the whole [album], so I went in and sweetened up a lot of music for her, adding some guitars to &apos;Lucky Star&apos;, some voices, some magic... I just wanted to do the best job I could do for her. When we would playback &apos;Holiday&apos; or &apos;Lucky Star&apos;, you could see that she was overwhelmed by how great it all sounded.&quot; — &lt;a href=&quot;https://en.wikipedia.org/wiki/John_Benitez&quot;&gt;John Benitez&lt;/a&gt;, producer of Madonna&apos;s first album, talking about Madonna and the album. &lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now take a song like &lt;em&gt;&quot;Snowgirl&quot;&lt;/em&gt;, off of The Pop Group&apos;s debut album, &lt;a href=&quot;https://en.wikipedia.org/wiki/Y_(album)&quot;&gt;Y&lt;/a&gt;, who &lt;a href=&quot;https://en.wikipedia.org/wiki/Stylus_Magazine&quot;&gt;Stylus Magazine&lt;/a&gt; wrote that the &quot;political punk tunes are deconstructed so that only the skeleton remains, and weaving between those bare bones are some of the nastiest sounds ever made.&quot; &lt;sup id=&quot;fnref-3&quot;&gt;&lt;a href=&quot;#fn-3&quot; class=&quot;footnote-ref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;350px&quot; src=&quot;https://www.youtube.com/embed/Pkib-F9n5HU&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p class=&quot;caption&quot;&gt;The Pop Group&apos;s &quot;Snowgirl&quot;. A discordant piano ballad accompanied by guitars that sound like they&apos;re on the verge of unrepairable destruction, angular bass lines, and delay drenched drums and vocals not uncommon in dub and reggae music.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Pitchfork_(website)&quot;&gt;Pitchfork&lt;/a&gt; said, &quot;unlike most of the late-70s&apos; no-wave types (and perennial imitators), The Pop Group were less concerned with eschewing convention than with vehemently eviscerating it.&quot;&lt;/p&gt;
&lt;p&gt;The album has had a lasting impact, with artists such as the &lt;a href=&quot;https://en.wikipedia.org/wiki/Sonic_Youth&quot;&gt;Sonic Youth&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Nick_Cave&quot;&gt;Nick Cave&lt;/a&gt; citing the album as an influence on their work.&lt;/p&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;350px&quot; src=&quot;https://www.youtube.com/embed/BUC2GmzJpGY&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p class=&quot;caption&quot;&gt;Nick Cave would go on to create &quot;The Birthday Party&quot;, one of the most influential post-punk bands of the 70s and early 80s.&lt;/p&gt;
&lt;p&gt;Watch Sonic Youth perform &lt;em&gt;&quot;The Burning Spear&quot;&lt;/em&gt; live below. Guitarist, Thurson Moore wedges a drumstick inbetween the fret and strings of his guitar and uses another drumstick to get some novel sounds out of the instrument.&lt;/p&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;350px&quot; src=&quot;https://www.youtube.com/embed/c1YVPanmh0Q?start=16&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p class=&quot;caption&quot;&gt;Sonic Youth performing &quot;The Burning Spear&quot;, the first SY song ever written.&lt;/p&gt;
&lt;p&gt;The Pop Group might not be where discordant music started, but for what I spend most of my time listening to, it very well might as well be.&lt;/p&gt;
&lt;p&gt;Here&apos;s another interesting one from &lt;a href=&quot;https://en.wikipedia.org/wiki/James_Chance_and_the_Contortions&quot;&gt;James Chance and the Contortions&lt;/a&gt;, no-wave band of the 70s that I describe as a mix between James Brown and The Pop Group.&lt;/p&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;350px&quot; src=&quot;https://www.youtube.com/embed/uCI24Lt9aNQ&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p class=&quot;caption&quot;&gt;James Chance and the Contortions are placed under the genres of No wave, punk jazz, avant-funk, dance-punk.&lt;/p&gt;
&lt;p&gt;Finally, my favourite band of all time, before Nick Cave went Americana, he was in the influential &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Birthday_Party_(band)&quot;&gt;Birthday Party&lt;/a&gt;, which wouldn&apos;t exist without The Pop Group.&lt;/p&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;350px&quot; src=&quot;https://www.youtube.com/embed/Q88nEF9cbbk?start=2010&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p class=&quot;caption&quot;&gt;The Birthday Party&apos;s influence has been far-reaching, and they have been called &quot;one of the darkest and most challenging post-punk groups to emerge in the early &apos;80s.&quot; - &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Birthday_Party_(band)&quot;&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;Sweetening-things-for-public-consumption&quot; style=&quot;position:relative;&quot;&gt;Sweetening things for public consumption&lt;a href=&quot;#Sweetening-things-for-public-consumption&quot; aria-label=&quot;Sweetening things for public consumption permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Unless you&apos;re specifically passionate about &lt;strong&gt;architecture&lt;/strong&gt; and aesthetic, it&apos;s easy to never notice any of the craftsmanship on the structures that we move between everyday. Although, if you take a walk around the UofT campus in Toronto, you&apos;ll have a hard time not noticing the &lt;a href=&quot;https://www.google.com/search?q=john+P.+Robarts+Research+Library&amp;#x26;source=lnms&amp;#x26;tbm=isch&amp;#x26;sa=X&amp;#x26;ved=0ahUKEwi0x8HiqbfkAhVFaq0KHZmjAecQ_AUIEygC&amp;#x26;biw=1186&amp;#x26;bih=811&quot;&gt;John P. Robarts Research Library&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With respect to &lt;strong&gt;web design&lt;/strong&gt;, the best design is &lt;strong&gt;invisible&lt;/strong&gt;. The principle states that good design is not something the average user looks at and says “wow, that’s a great design!” Good design is something that is easy to use, read and interact with. &lt;sup id=&quot;fnref-4&quot;&gt;&lt;a href=&quot;#fn-4&quot; class=&quot;footnote-ref&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Brutalist websites built with HTML, CSS, and JavaScript don&apos;t aim to mask, sweeten, lighten or smoothen the borders on the rough and ugly edges. Instead, they draw attention to them. That&apos;s what makes them interesting and memorable.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sometimes when things are overly sweet, they tend to alienate us.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;My-Brutalist-Junk-Jazz-playlist&quot; style=&quot;position:relative;&quot;&gt;My &quot;Brutalist&quot; Junk Jazz playlist&lt;a href=&quot;#My-Brutalist-Junk-Jazz-playlist&quot; aria-label=&quot;My Brutalist Junk Jazz playlist permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you&apos;re into discordant music, check out one of my playlists titled &quot;Junk Jazz&quot; on Spotify.&lt;/p&gt;
&lt;iframe src=&quot;https://open.spotify.com/embed/playlist/0M9314rqdlCm1Ga2aFsipb&quot; width=&quot;100%&quot; height=&quot;350px&quot; frameborder=&quot;0&quot; allowtransparency=&quot;true&quot; allow=&quot;encrypted-media&quot;&gt;&lt;/iframe&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;See &lt;a href=&quot;https://trydesignlab.com/blog/brutalist-websites-5-things-designers-learn-brutalism/&quot;&gt;Brutalism definition&lt;/a&gt;&lt;/p&gt;
&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Rooksby, Rikky (2004). The Complete Guide to the Music of Madonna. &lt;a href=&quot;https://en.wikipedia.org/wiki/Music_Sales_Group&quot;&gt;Omnibus Press&lt;/a&gt;. ISBN 0-7119-9883-3.&lt;/p&gt;
&lt;a href=&quot;#fnref-2&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;Howard, Ed (March 22, 2004). &lt;a href=&quot;http://stylusmagazine.com/&quot;&gt;&quot;Top 101-200 Albums Favorite Albums Ever&quot;&lt;/a&gt;. Stylus Magazine. Retrieved September 11, 2014.&lt;/p&gt;
&lt;a href=&quot;#fnref-3&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;DesignShack (&lt;a href=&quot;https://designshack.net/articles/graphics/10-reasons-why-the-best-design-is-invisible/&quot;&gt;&quot;10 Reasons Why the Best Design Is Invisible&quot;&lt;/a&gt;)&lt;/p&gt;
&lt;a href=&quot;#fnref-4&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Comparison of Domain-Driven Design and Clean Architecture Concepts]]></title><description><![CDATA[Before I got into software design and architecture, my code was hurting 🤕. I spent a lot of time doing rework, writing untestable code…]]></description><link>https://khalilstemmler.com/articles/software-design-architecture/domain-driven-design-vs-clean-architecture/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/software-design-architecture/domain-driven-design-vs-clean-architecture/</guid><pubDate>Tue, 05 Nov 2019 04:05:26 GMT</pubDate><content:encoded>&lt;p&gt;Before I got into software design and architecture, &lt;u&gt;my code was hurting&lt;/u&gt; 🤕.&lt;/p&gt;
&lt;p&gt;I spent a lot of time doing rework, writing untestable code, trying to invent my own (bad) abstractions, and putting all my business logic into &lt;a href=&quot;/wiki/anemic-domain-model/&quot;&gt;anemic&lt;/a&gt; services.&lt;/p&gt;
&lt;p&gt;Eventually, I ended up reading &lt;strong&gt;Clean Architecture&lt;/strong&gt; by Uncle Bob and then &lt;strong&gt;Domain-Driven Design&lt;/strong&gt; by Eric Evans.&lt;/p&gt;
&lt;p&gt;Domain-Driven Design, initially written in 2003 by Eric Evans, introduced new approaches towards designing software by using a layered architecture with a rich domain model in the center.&lt;/p&gt;
&lt;p&gt;Uncle Bob wrote Clean Architecture in 2017 and summarized his research on what constitutes a clean architecture, &lt;em&gt;also&lt;/em&gt; using a layered architecture with a domain layer in the center.&lt;/p&gt;
&lt;p&gt;Even through there&apos;s some overlap between the concepts that both of these books introduced, there&apos;s a little bit of confusion on the definitions of the constructs.&lt;/p&gt;
&lt;p&gt;That&apos;s what I&apos;d like to clear up.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Over the past year or so, I&apos;ve realized that in software development,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There&apos;s a construct for everything.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For &lt;em&gt;validation logic&lt;/em&gt;, we have &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;Value Objects&lt;/a&gt;. For abstracting the challenges of retrieving and persisting data, we have &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;repositories&lt;/a&gt;. A &lt;em&gt;generally cohesive group of code&lt;/em&gt; can be called a &lt;strong&gt;component&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For just about every scenario, and at every layer of the layered architecture, there exists a construct or design pattern we can use to solve our problems.&lt;/p&gt;
&lt;p&gt;The second thing I&apos;ve learned is,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Every developer has a different name for these constructs&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Depending on who you ask, a &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;Use Case&lt;/a&gt; might only be known to someone as an &lt;strong&gt;application service&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Some developers see &lt;strong&gt;domain services&lt;/strong&gt; and &lt;strong&gt;application services&lt;/strong&gt; as the same thing. &lt;/p&gt;
&lt;p&gt;Ironic to the essence of DDD, it&apos;s the lack of a shared understanding towards the tools that we use in our &lt;em&gt;domain&lt;/em&gt; (software development, that is) that makes it difficult for us to have conversations about software design and architecture.&lt;/p&gt;
&lt;p&gt;Because we so regularly involve topics from both DDD and Clean Architecture on this blog (I&apos;ll refer to Clean Architecture as &lt;em&gt;CA&lt;/em&gt; from now on), I think it would be a good idea to attempt to identify the mapping between the two.&lt;/p&gt;
&lt;p&gt;By the end of this article, should:&lt;/p&gt;
&lt;ul class=&quot;special-quote&quot;&gt;
  &lt;li&gt;Understand the similarities and differences between concepts introduced by DDD and CA towards implementing a layered architecture.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;Starting from the center of the layered architecture, we have the concept of &lt;strong&gt;entities&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Entities&quot; style=&quot;position:relative;&quot;&gt;Entities&lt;a href=&quot;#Entities&quot; aria-label=&quot;Entities permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/ddd-comparison/domain-layer.svg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Comparison-between-books&quot; style=&quot;position:relative;&quot;&gt;Comparison between books&lt;a href=&quot;#Comparison-between-books&quot; aria-label=&quot;Comparison between books permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Book&lt;/th&gt;
&lt;th&gt;Known as&lt;/th&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Domain-Driven Design (DDD)&lt;/td&gt;
&lt;td&gt;Entity (and sometimes Aggregate)&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clean Architecture (CA)&lt;/td&gt;
&lt;td&gt;Entity&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;Observations&quot; style=&quot;position:relative;&quot;&gt;Observations&lt;a href=&quot;#Observations&quot; aria-label=&quot;Observations permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;From &lt;strong&gt;Clean Architecture&lt;/strong&gt;, Uncle Bob said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;An Entity is an object within our computer system that embodies a small set of critical business rules operating on &lt;u&gt;Critical Business Data&lt;/u&gt;.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I like this definition! The critical business data is comparable to &lt;em&gt;domain logic/business rules&lt;/em&gt; in DDD.&lt;/p&gt;
&lt;p&gt;It also sounds a lot like we&apos;re talking about &lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;aggregates&lt;/a&gt; (a very specific type of entity) because in aggregate design, we put a lot of effort into identifying the exact aggregate boundaries in order to keep it small.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;The interface of the Entity consists of the functions that implement the Critical Business Rules that operate on that data&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This right here sounds like we&apos;re talking about designing &lt;a href=&quot;/articles/typescript-domain-driven-design/intention-revealing-interfaces/&quot;&gt;intention revealing interfaces&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;That means the API for entity (the methods that it exposes) should only be operations that are valid and make sense to our domain. &lt;/p&gt;
&lt;p&gt;In a &lt;code class=&quot;language-text&quot;&gt;Job&lt;/code&gt; aggregate, if the &lt;a href=&quot;/wiki/invariant/&quot;&gt;class invariant&lt;/a&gt; (business rule) said that the &lt;code class=&quot;language-text&quot;&gt;Job&lt;/code&gt;&apos;s &lt;code class=&quot;language-text&quot;&gt;paymentType&lt;/code&gt; can&apos;t be changed after people applied to it, we &lt;u&gt;shouldn&apos;t even&lt;/u&gt; expose a &lt;a href=&quot;/blogs/typescript/getters-and-setters/&quot;&gt;setter&lt;/a&gt; for &lt;code class=&quot;language-text&quot;&gt;paymentType&lt;/code&gt;, because doing that would introduce a surface area for the class invariants to be circumvented.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;domain/job.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Job&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;JobProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;paymentType&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PaymentType &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;paymentType&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// No setter exposed&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;updatePaymentType&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;paymentType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PaymentType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasApplicants&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Can&apos;t update payment type 
        on a job that has applicants&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;paymentType &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; paymentType&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;To learn how to use entities in your Node.js / TypeScript projects to encapsulate &lt;i&gt;critical business data&lt;/i&gt;, read &lt;a href=&quot;/articles/typescript-domain-driven-design/entities/&quot;&gt;&quot;Understanding Domain Entities [with Examples] - DDD w/ TypeScript&quot;&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;To learn how to design aggregates, read &lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;&quot;How to Design and Persist Aggregates - DDD w/ TypeScript&quot;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Domain-Services&quot; style=&quot;position:relative;&quot;&gt;Domain Services&lt;a href=&quot;#Domain-Services&quot; aria-label=&quot;Domain Services permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/ddd-comparison/domain-layer.svg&quot;&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Book&lt;/th&gt;
&lt;th&gt;Known as&lt;/th&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Domain-Driven Design (DDD)&lt;/td&gt;
&lt;td&gt;Domain Service&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clean Architecture (CA)&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In DDD, a &lt;strong&gt;Domain Service&lt;/strong&gt; is a specific type of domain layer class that we use when we want to put some domain logic that relies on two or more entities. &lt;/p&gt;
&lt;p&gt;We use Domain Services when putting the logic on a particular entity would break encapsulation and require the entity to know about things it really shouldn&apos;t be concerned with. &lt;/p&gt;
&lt;p&gt;For example, in &lt;a href=&quot;https://github.com/stemmlerjs/ddd-forum&quot;&gt;DDDForum.com&lt;/a&gt;, when we want to &lt;code class=&quot;language-text&quot;&gt;upvotePost(member: Member, post: Post, existingVotes: PostVote[])&lt;/code&gt;, which entity&apos;s class should that method belong to?&lt;/p&gt;
&lt;p&gt;Is it the &lt;code class=&quot;language-text&quot;&gt;Member&lt;/code&gt; entity?&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;PostVote&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;None, because it doesn&apos;t belong to one, really.&lt;/p&gt;
&lt;p&gt;I probably would have tried to use &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt; but since &lt;code class=&quot;language-text&quot;&gt;Member&lt;/code&gt; isn&apos;t within the &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt; aggregate boundary, it&apos;s apparent that we need something else.&lt;/p&gt;
&lt;p&gt;This is when we use Domain Services: when we have some business logic that involves multiple entities and putting it into an arbitrary selection of one of them would break domain model encapsulation.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;domain/services/postService.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;/**
   * Demonstrating the use of a domain service to
   * encapsulate domain logic that involves several
   * entities.
   */&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;upvotePost&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    post&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Post&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    member&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Member&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    existingVotesOnPostByMember&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostVote&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UpvotePostResponse &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; existingUpvote&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostVote &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; existingVotesOnPostByMember
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; v&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isUpvote&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// If already upvoted, do nothing&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; upvoteAlreadyExists &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;existingUpvote&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;upvoteAlreadyExists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;token comment&quot;&gt;// If downvoted, remove the downvote&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; existingDownvote&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostVote &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; existingVotesOnPostByMember
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; v&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isDownvote&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; downvoteAlreadyExists &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;existingDownvote&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;downvoteAlreadyExists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeVote&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;existingDownvote&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Otherwise, add upvote&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; upvoteOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; PostVote
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createUpvote&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;member&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;memberId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;upvoteOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;upvoteOrError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; upvote&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostVote &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; upvoteOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addVote&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;upvote&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is a really specific tactical domain modeling tool, so I&apos;m not shocked to see that it wasn&apos;t mentioned in CA.&lt;/p&gt;
&lt;h2 id=&quot;Application-Services&quot; style=&quot;position:relative;&quot;&gt;Application Services&lt;a href=&quot;#Application-Services&quot; aria-label=&quot;Application Services permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/ddd-comparison/application-layer2.svg&quot;&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Book&lt;/th&gt;
&lt;th&gt;Known as&lt;/th&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Domain-Driven Design (DDD)&lt;/td&gt;
&lt;td&gt;Application Service&lt;/td&gt;
&lt;td&gt;Application&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clean Architecture (CA)&lt;/td&gt;
&lt;td&gt;Use Case&lt;/td&gt;
&lt;td&gt;Application&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In &lt;strong&gt;Clean Architecture&lt;/strong&gt;, Uncle Bob describes &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt; as the main &lt;strong&gt;features&lt;/strong&gt; of the application. &lt;/p&gt;
&lt;p&gt;These are all the things our application can do.&lt;/p&gt;
&lt;p&gt;And in a previous article, we discovered that use cases were either &lt;a href=&quot;/articles/oop-design-principles/command-query-segregation/&quot;&gt;commands or queries&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Use Cases (a Clean Architecture term) are similar to &lt;strong&gt;Application Services&lt;/strong&gt; in DDD. At least their &lt;em&gt;relative positioning&lt;/em&gt; is. &lt;/p&gt;
&lt;p&gt;In DDD, &lt;strong&gt;Application Services&lt;/strong&gt; (application layer concerns, obviously) represent commands or queries (like &lt;code class=&quot;language-text&quot;&gt;createComment&lt;/code&gt; - COMMAND or &lt;code class=&quot;language-text&quot;&gt;getCommentById&lt;/code&gt; - QUERY) that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Contain no domain-specific business logic.&lt;/li&gt;
&lt;li&gt;Are used in order to fetch domain entities (and anything else) from persistence and the outside world.&lt;/li&gt;
&lt;li&gt;Either passes of control to an Aggregate to execute domain logic by using a method of the Aggregate, or passes off several entities to a Domain Service to facilitate their interaction.&lt;/li&gt;
&lt;li&gt;Have low-levels of &lt;a href=&quot;https://en.wikipedia.org/wiki/Cyclomatic_complexity&quot;&gt;Cyclomatic Complexity&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, the application service for the &lt;code class=&quot;language-text&quot;&gt;UpvotePost&lt;/code&gt; command would:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get the member, post, and post votes&lt;/li&gt;
&lt;li&gt;Pass them to the domain service&lt;/li&gt;
&lt;li&gt;Save the transaction if it was successful.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;filename&quot;&gt;useCases/upvotePost/UpvotePost.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UseCase &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../../shared/core/UseCase&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpvotePostDTO &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./UpvotePostDTO&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IMemberRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../repos/memberRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IPostRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../repos/postRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; left&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; right&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Result &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../../shared/core/Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AppError &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../../shared/core/AppError&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpvotePostErrors &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./UpvotePostErrors&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Member &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/member&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Post &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/post&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IPostVotesRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../repos/postVotesRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; PostVote &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/postVote&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; PostService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/services/postService&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UpvotePostResponse &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./UpvotePostResponse&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpvotePost&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpvotePostDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpvotePostResponse&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; memberRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IMemberRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; postRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IPostRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; postVotesRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IPostVotesRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; postService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token parameter&quot;&gt;memberRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IMemberRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    postRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IPostRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    postVotesRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IPostVotesRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    postService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostService&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;memberRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; memberRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; postRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postVotesRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; postVotesRepo
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; postService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UpvotePostDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UpvotePostResponse&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; member&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Member&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; post&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Post&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; existingVotesOnPostByMember&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostVote&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      
      &lt;span class=&quot;token comment&quot;&gt;// Get the member&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        member &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;memberRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getMemberByUserId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpvotePostErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;MemberNotFoundError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Get the post&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        post &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getPostBySlug&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;slug&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UpvotePostErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PostNotFoundError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;slug&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Get the existing post votes&lt;/span&gt;
      existingVotesOnPostByMember &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postVotesRepo
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getVotesForPostByMemberId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  member&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;memberId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Allow the domain service to exec&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; upvotePostResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postService
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;upvotePost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; member&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; existingVotesOnPostByMember&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// If failed, return a failure result&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;upvotePostResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isLeft&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;upvotePostResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Otherwise, commit the transaction&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Success!&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AppError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UnexpectedError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&apos;s Application Services.&lt;/p&gt;
&lt;p&gt;In Uncle Bob-land, Use Cases &lt;em&gt;do&lt;/em&gt; allow for business logic, but there&apos;s a differentiation between what consistutes &lt;em&gt;application layer&lt;/em&gt; business logic and what constitutes &lt;em&gt;domain business logic&lt;/em&gt;. I haven&apos;t seen the Clean Coder videos myself to dive deeper on this differentiation, so maybe someone else can provide some more clarification, but it does sound quite similar to the way application and domain layer logic is organized in DDD.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I think these are the primary building blocks and areas of confusion between implementing the concepts from Clean Architecture and Domain-Driven Design.&lt;/p&gt;
&lt;p&gt;It just goes to show how you can argue back and forth with someone about what the correct tool for the job is, before identifying the fact that you were talking about the same thing, semantically.&lt;/p&gt;
&lt;p&gt;Good to know!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to Prerender Comments | Gatsbyjs Guide]]></title><description><![CDATA[When Disqus comments stopped being awesome, I was left without comments on my blog for a while.  Not too long after, Tania Rascia wrote an…]]></description><link>https://khalilstemmler.com/articles/gatsbyjs/prerender-comments-for-seo/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/gatsbyjs/prerender-comments-for-seo/</guid><pubDate>Fri, 25 Oct 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;When Disqus comments &lt;a href=&quot;https://kinsta.com/blog/disqus-ads/&quot;&gt;stopped being awesome&lt;/a&gt;, I was left without comments on my blog for a while. &lt;/p&gt;
&lt;p&gt;Not too long after, &lt;a href=&quot;https://taniarascia.com&quot;&gt;Tania Rascia&lt;/a&gt; wrote an awesome guide on how to &quot;&lt;a href=&quot;https://www.gatsbyjs.org/blog/2019-08-27-roll-your-own-comment-system/&quot;&gt;Roll Your Own Comment&lt;/a&gt;&quot; system. &lt;/p&gt;
&lt;p&gt;I hooked it up and people started leaving (mostly) productive comments. &lt;/p&gt;
&lt;p&gt;Today, I use the comments to answer questions about Domain-Driven Design, Clean Architecture, and Enterprise Node.js with TypeScript. They&apos;ve been helpful in informing me what I should spend the majority of my time writing about. &lt;/p&gt;
&lt;p&gt;Not only that, but I tend to get some really good questions that really force me to think, and I enjoy the challenge of trying to make myself understood.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;At some point I realized that lots of people might be asking the same questions that I get asked on my blog, so it would be a good idea if Google was able to see the comments when they index my site.&lt;/p&gt;
&lt;p&gt;Because the comments are dynamic and get loaded by the client for each route, when Google crawls my site, it doesn&apos;t wait for the comments to load.&lt;/p&gt;
&lt;p&gt;This is the problem that &lt;a href=&quot;https://www.netlify.com/blog/2016/11/22/prerendering-explained/&quot;&gt;prerendering&lt;/a&gt; solves.&lt;/p&gt;
&lt;p&gt;In this article, I&apos;m going to show you how you can prerender comments on your Gatsby blog.&lt;/p&gt;
&lt;h2 id=&quot;Prerequisites&quot; style=&quot;position:relative;&quot;&gt;Prerequisites&lt;a href=&quot;#Prerequisites&quot; aria-label=&quot;Prerequisites permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;You&apos;re familiar with Gatsby, the site generator for React.&lt;/li&gt;
&lt;li&gt;You&apos;ve read Tania&apos;s article, &quot;&lt;a href=&quot;https://www.gatsbyjs.org/blog/2019-08-27-roll-your-own-comment-system/&quot;&gt;Roll Your Own Comment System&lt;/a&gt;&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Create-a-GET-commentsall-API-route&quot; style=&quot;position:relative;&quot;&gt;Create a GET /comments/all API route&lt;a href=&quot;#Create-a-GET-commentsall-API-route&quot; aria-label=&quot;Create a GET commentsall API route permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&apos;re going to need to pull in all the comments everytime we build our Gatsby site.&lt;/p&gt;
&lt;p&gt;This should be relatively straightforward if you&apos;ve followed Tania&apos;s guide. A simple &lt;code class=&quot;language-text&quot;&gt;SELECT *&lt;/code&gt; will do just fine. And when you get a lot of comments, it would make sense to paginate the responses.&lt;/p&gt;
&lt;p&gt;You might not need my help here, but for context, I&apos;ll show you how I did mine.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Note:&lt;/b&gt; I use the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;Clean Architecture approach&lt;/a&gt; to separate the concerns of my code. Depending on amount of stuff your backend does, it might not be necessary.&lt;/p&gt;
&lt;p&gt;Using the &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;repository pattern&lt;/a&gt; to encapsulate potential complexity of interacting with a relational database, we can retrieve &lt;code class=&quot;language-text&quot;&gt;comments&lt;/code&gt; from our MySQL db by executing a raw query and mapping the results into &lt;code class=&quot;language-text&quot;&gt;Comment&lt;/code&gt; domain objects.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;comments/infra/repos/implementations/commentRepo.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CommentRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ICommentRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getAllComments&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Comment&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; query &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;SELECT * FROM comments ORDER BY created_at DESC;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;err&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; CommentMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;r&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;filename&quot;&gt;comments/domain/commentMap.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Comment &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../models/Comment&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CommentMap&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Comment &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      comment&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;comment&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      createdAt&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;created_at&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      approved&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;approved &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      parentCommentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parent_comment_id
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, all I have to do is create a new &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use case&lt;/a&gt; called &lt;code class=&quot;language-text&quot;&gt;GetAllComments&lt;/code&gt; that does just that- gets all comments.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;comments/useCases/getAllComments/getAllComments.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ICommentRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../repos/CommentRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GetAllComments&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; commentRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ICommentRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;commentRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ICommentRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;commentRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; commentRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;commentRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAllComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; comments&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now I&apos;ll write the controller:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;comments/useCases/getAllComments/getAllCommentsController.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; GetAllComments &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./GetAllComments&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;GetAllCommentsController&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;useCase&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GetAllComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; useCase&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; comments &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Failed&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Hook everything up with some manual &lt;a href=&quot;/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;Dependency Injection&lt;/a&gt; and then export the controller.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;comments/useCases/getAllComments/index.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; GetAllComments &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./GetAllComments&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; commentRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../repos&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; GetAllCommentsController &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./GetAllCommentsController&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; getAllComments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GetAllComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;commentRepo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; getAllCommentsController &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetAllCommentsController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;getAllComments&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  getAllCommentsController
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, I&apos;ll hook the controller up to our &lt;code class=&quot;language-text&quot;&gt;comments&lt;/code&gt; API (Express.js route).&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;app.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; express &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;express&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; getAllCommentsController &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../../useCases/admin/getAllComments&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; commentsRouter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Router&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

commentsRouter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/all&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getAllCommentsController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  commentsRouter
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Testing-fetching-the-comments&quot; style=&quot;position:relative;&quot;&gt;Testing fetching the comments&lt;a href=&quot;#Testing-fetching-the-comments&quot; aria-label=&quot;Testing fetching the comments permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Push and deploy that code then try to get your comments! Here&apos;s what it looks like for me.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/gatsby/fetched-comments-postman.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Nice! Now that we&apos;ve &lt;strong&gt;created the data source&lt;/strong&gt;, we need to &lt;u&gt;create a plugin&lt;/u&gt; for Gatbsy so that it knows how to fetch it and then insert it into Gatsby&apos;s data layer so that we can prerender comments at build time.&lt;/p&gt;
&lt;h2 id=&quot;Creating-a-source-plugin-to-source-comments-into-Gatsbys-data-layer&quot; style=&quot;position:relative;&quot;&gt;Creating a source plugin to source comments into Gatsby&apos;s data layer&lt;a href=&quot;#Creating-a-source-plugin-to-source-comments-into-Gatsbys-data-layer&quot; aria-label=&quot;Creating a source plugin to source comments into Gatsbys data layer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &lt;em&gt;source&lt;/em&gt; plugin is one of Gatsby&apos;s two types of plugins. &lt;em&gt;Source&lt;/em&gt; plugins simply pull in data from local or remote locations.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Essential Gatsby reading&lt;/b&gt;: &quot;&lt;a href=&quot;https://www.gatsbyjs.org/docs/creating-a-source-plugin/&quot;&gt;Creating a Source Plugin&lt;/a&gt;&quot;.&lt;/p&gt;
&lt;h3 id=&quot;Setup&quot; style=&quot;position:relative;&quot;&gt;Setup&lt;a href=&quot;#Setup&quot; aria-label=&quot;Setup permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As per the docs, we&apos;ll create a folder called &lt;code class=&quot;language-text&quot;&gt;plugins&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; plugins&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Inside that folder, let&apos;s create &lt;em&gt;another&lt;/em&gt; folder. This will be the name of the local plugin that we&apos;re about to write.&lt;/p&gt;
&lt;p&gt;In order to not think about it, the docs also have a reference on &lt;a href=&quot;https://www.gatsbyjs.org/docs/naming-a-plugin/&quot;&gt;naming plugins&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let&apos;s name our plugin &lt;code class=&quot;language-text&quot;&gt;gatsby-source-self-hosted-comments&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; plugins
&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; gatsby-source-self-hosted-comments&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the new subfolder, let&apos;s initialize it as an npm project, add a few dependencies, and create a &lt;code class=&quot;language-text&quot;&gt;gatsby-node&lt;/code&gt; file.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;cd gatsby-source-self-hosted-comments
npm init -y
npm install --save axios
touch gatsby-node.js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Writing-the-plugin&quot; style=&quot;position:relative;&quot;&gt;Writing the plugin&lt;a href=&quot;#Writing-the-plugin&quot; aria-label=&quot;Writing the plugin permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The plugin needs to do two things.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Fetch the comments from our API.&lt;/li&gt;
&lt;li&gt;Iterate through each comment and create a &lt;code class=&quot;language-text&quot;&gt;Comment&lt;/code&gt; graphql node for it.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;filename&quot;&gt;plugins/gatsby-source-self-hosted-comments/gatsby-node.js&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; axios &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;axios&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; crypto &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;crypto&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * @desc Marshalls a comment into the format that
 * we need it, and adds the required attributes in
 * order for graphql to register it as a node.
 */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processComment&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; commentData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; comment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    text&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; comment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;comment&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    createdAt&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; comment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;createdAt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; comment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    approved&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; comment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;approved&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    parentCommentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; comment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parentCommentId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;commentData&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Required fields.&lt;/span&gt;
    id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; comment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    parent&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    children&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    internal&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Comment&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      contentDigest&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; crypto
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createHash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;md5&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;commentData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;digest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;hex&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;sourceNodes&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; actions &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; configOptions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createNode &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; actions
  &lt;span class=&quot;token comment&quot;&gt;// Create nodes here.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// We will include the API as a gatsby-config option when we hook the&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// plugin up. &lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; apiUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; configOptions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Fetch the data&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; axios&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;apiUrl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;comments&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Process data into nodes.&lt;/span&gt;
    comments&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;comment&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;processComment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;comment&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Tell-Gatsby-to-use-the-plugin&quot; style=&quot;position:relative;&quot;&gt;Tell Gatsby to use the plugin&lt;a href=&quot;#Tell-Gatsby-to-use-the-plugin&quot; aria-label=&quot;Tell Gatsby to use the plugin permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In order to use the newly written plugin, we need to add it to our &lt;code class=&quot;language-text&quot;&gt;gatsby-config.js&lt;/code&gt; in the root folder of our project.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;name&lt;/strong&gt; that we use is the name of the &lt;em&gt;folder&lt;/em&gt; that we created in &lt;code class=&quot;language-text&quot;&gt;plugins/&lt;/code&gt;; that is- &lt;code class=&quot;language-text&quot;&gt;gatsby-source-self-hosted-comments&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;gatsby-config.js&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  plugins&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      resolve&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;gatsby-source-self-hosted-comments&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      options&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;https://khalil-stemmler-backend.herokuapp.com/comments/all/&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Test-retrieving-comments-from-Gatsby-with-the-GraphiQL-explorer&quot; style=&quot;position:relative;&quot;&gt;Test retrieving comments from Gatsby with the GraphiQL explorer&lt;a href=&quot;#Test-retrieving-comments-from-Gatsby-with-the-GraphiQL-explorer&quot; aria-label=&quot;Test retrieving comments from Gatsby with the GraphiQL explorer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Gatsby comes with a GraphQL explorer that we can use to see the current data in Gatsby&apos;s data layer. &lt;/p&gt;
&lt;p&gt;In order to bring it up, let&apos;s first clear Gatsby&apos;s cache by running &lt;code class=&quot;language-text&quot;&gt;gatsby clean&lt;/code&gt; and then starting Gatsby locally with &lt;code class=&quot;language-text&quot;&gt;gatsby develop&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you navigate to &lt;code class=&quot;language-text&quot;&gt;localhost:8000/__graphql&lt;/code&gt;, we can run an &lt;code class=&quot;language-text&quot;&gt;allComment&lt;/code&gt; query to return all the comments.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  allComment &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    edges &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      node &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        name
        parentCommentId
        text
        url
        createdAt
        approved
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If all is well, you should see your comments!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/gatsby/graphql-query.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Lovely. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Loading&lt;/strong&gt; comments into Gatsby on startup was the first step. Now we need to write some queries and hook up our prerendered comments to the blog post template.&lt;/p&gt;
&lt;h2 id=&quot;Updating-the-Blog-Post-template-to-load-comments&quot; style=&quot;position:relative;&quot;&gt;Updating the Blog Post template to load comments&lt;a href=&quot;#Updating-the-Blog-Post-template-to-load-comments&quot; aria-label=&quot;Updating the Blog Post template to load comments permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Originally, the only thing the blog post template needed to load was the blog post that matches the &lt;code class=&quot;language-text&quot;&gt;$id&lt;/code&gt; provided at build time as context variables.&lt;/p&gt;
&lt;p&gt;Now, we also want to load the comments. &lt;/p&gt;
&lt;p&gt;We can load them both by aliasing the &lt;code class=&quot;language-text&quot;&gt;markdownRemark&lt;/code&gt; as &lt;code class=&quot;language-text&quot;&gt;post&lt;/code&gt; and aliasing the &lt;code class=&quot;language-text&quot;&gt;allComment&lt;/code&gt; query as &lt;code class=&quot;language-text&quot;&gt;comments&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;templates/blog-post.js&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pageQuery &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; graphql&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
  query BlogPostByID($id: String!) {
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    post: markdownRemark(id: { eq: $id }) {&lt;/span&gt;      id
      html
      fields {
        slug
        readingTime {
          text
        }
      }
      frontmatter {
        date
        updated
        title
        templateKey
        description
        tags
        image
        category
        anchormessage
      }
    }
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    comments: allComment {&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      edges {&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        node {&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          ...CommentFields&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        }&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      }&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    }&lt;/span&gt;  }
&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the same &lt;a href=&quot;https://github.com/stemmlerjs/khalilstemmler-website-2019/blob/aebe1ca8d338fefaf049fd1e2ad170f61207d023/src/templates/blog-post.js&quot;&gt;file&lt;/a&gt;, we do 3 things to handle the query.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We deconstruct the &lt;code class=&quot;language-text&quot;&gt;post&lt;/code&gt; from &lt;code class=&quot;language-text&quot;&gt;props.data&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;We get the comments from the &lt;em&gt;current&lt;/em&gt; blog post by filtering in on the &lt;code class=&quot;language-text&quot;&gt;slug&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We pass the comments to our &lt;code class=&quot;language-text&quot;&gt;Article&lt;/code&gt; component.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;filename&quot;&gt;templates/blog-post.js&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;BlogPost&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; post &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; fields&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; frontmatter&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; html &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; post&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; slug &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fields&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    image&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    description&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    date&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    updated&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    category&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    tags
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; frontmatter&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;comments&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;edges&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; slug&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;node&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; seoTags &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tags &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; tags &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  seoTags &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; seoTags&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;category&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Layout
      seo&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        keywords&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; seoTags&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        image&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        description&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        pageType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PageType&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;ARTICLE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        datePublished&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; date&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        dateModified&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; updated&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        slug&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        cardSize&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TwittterCardSize&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;SMALL&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;article-layout-container&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Article
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;fields&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;frontmatter&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          html&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;html&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          comments&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;comments&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;        &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ArticleSideContent&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Layout&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Presenting-prerendered-data-on-the-server-and-live-data-in-production&quot; style=&quot;position:relative;&quot;&gt;Presenting prerendered data on the server and live data in production&lt;a href=&quot;#Presenting-prerendered-data-on-the-server-and-live-data-in-production&quot; aria-label=&quot;Presenting prerendered data on the server and live data in production permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The goal for us is to ensure that when the site is built on the server, it renders the pre-loaded content. &lt;u&gt;This is what&apos;s good for SEO&lt;/u&gt;. That&apos;s the whole reason why we&apos;re doing this.&lt;/p&gt;
&lt;p&gt;But we also want to make sure that when someone lands on a blog post, they&apos;re seeing the most up to date comments.&lt;/p&gt;
&lt;p&gt;In the &lt;code class=&quot;language-text&quot;&gt;Article&lt;/code&gt; component, we feed the &lt;code class=&quot;language-text&quot;&gt;comments&lt;/code&gt; through to a &lt;code class=&quot;language-text&quot;&gt;Comments&lt;/code&gt; component.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;article.js&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Article&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Component&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Comments comments&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;comments&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the &lt;code class=&quot;language-text&quot;&gt;Comments&lt;/code&gt; component is where the action happens.&lt;/p&gt;
&lt;p&gt;Here&apos;s the gist of it.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;comments.js&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; PropTypes &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;prop-types&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Editor &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./Editor&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Comment &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./Comment&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; TextInput &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../shared/text-input&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; SubmitButton &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../shared/buttons&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../styles/Comments.sass&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; commentService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../../services/commentService&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Comments&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Component&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;maxCommentLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;minCommentLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      isFetchingComments&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
      comments&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      commentText&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      commentSubmitted&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getCommentsFromAPI&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;location&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pathname&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isFetchingComments&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; commentService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isFetchingComments&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; comments &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;setState&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isFetchingComments&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; comments&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;componentDidMount&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCommentsFromAPI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;sortComments&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;createdAt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;createdAt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;isReply&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;comment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parentCommentId &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;presentComments&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;comments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; replies &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; comments&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isReply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    comments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; comments
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isReply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; commentReplies &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; replies&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parentCommentId &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;commentReplies&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;replies &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; commentReplies&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sortComments&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; comments
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sortComments&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getRealTimeComments&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;presentComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;comments&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getPrerenderedComments&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;presentComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;comments &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;comments &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getComments&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; window &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;undefined&apos;&lt;/span&gt; 
      &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getPrerenderedComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
      &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getRealTimeComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; commentText &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; numComments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; comments&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; hasComments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; numComments &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;comments-container&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;h3&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;numComments&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;numComments &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Comment&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Comments&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;h3&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;hasComments &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Be the first to leave a comment&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TextInput
          placeholder&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Name&quot;&lt;/span&gt;
          value&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          onChange&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updateFormField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Editor 
          text&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;commentText&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          handleChange&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updateFormField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;commentText&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          maxLength&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          placeholder&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Comment&quot;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;SubmitButton
          text&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Submit&quot;&lt;/span&gt;
          &lt;span class=&quot;token comment&quot;&gt;// icon&lt;/span&gt;
          onClick&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;submitComment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          loading&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          disabled&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isFormReady&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;comments&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;c&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Comment &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

Comments&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;propTypes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  comments&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PropTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;arrayOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PropTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    approved&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PropTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bool&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isRequired&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    createdAt&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PropTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PropTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PropTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    text&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PropTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PropTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isRequired
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The idea is that the comments passed &lt;em&gt;to&lt;/em&gt; this component through &lt;code class=&quot;language-text&quot;&gt;props&lt;/code&gt; are &lt;u&gt;prerendered comments&lt;/u&gt; while the comments that we retrieve and save to state by calling &lt;code class=&quot;language-text&quot;&gt;getCommentsFromAPI()&lt;/code&gt; within &lt;code class=&quot;language-text&quot;&gt;componentDidMount()&lt;/code&gt; are the &lt;u&gt;live, real-time comments&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;We can get the correct comments in context by testing to see if &lt;code class=&quot;language-text&quot;&gt;window&lt;/code&gt; is defined or not.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;comments.js&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;getComments&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; window &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;undefined&apos;&lt;/span&gt; 
      &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getPrerenderedComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
      &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getRealTimeComments&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If &lt;code class=&quot;language-text&quot;&gt;window&lt;/code&gt; isn&apos;t defined, then the code is running in a server; otherwise, it&apos;s being run by a real browser (in which case, we&apos;d want to present the real-time comments).&lt;/p&gt;
&lt;p&gt;That should do it!&lt;/p&gt;
&lt;h2 id=&quot;Verify-that-comments-are-preloaded&quot; style=&quot;position:relative;&quot;&gt;Verify that comments are preloaded&lt;a href=&quot;#Verify-that-comments-are-preloaded&quot; aria-label=&quot;Verify that comments are preloaded permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We can verify that comments are preloaded by creating a local build and then checking the resulting HTML in the &lt;code class=&quot;language-text&quot;&gt;public&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;Build the site using &lt;code class=&quot;language-text&quot;&gt;gatsby build&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;gatsby build&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then navigate to an &lt;code class=&quot;language-text&quot;&gt;index.html&lt;/code&gt; file for one of your blog posts that you know has comments. &lt;/p&gt;
&lt;p&gt;For me, I know that Igor left a comment on the &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design Intro&lt;/a&gt; article. &lt;/p&gt;
&lt;p&gt;Using &lt;code class=&quot;language-text&quot;&gt;CMD + F&lt;/code&gt; and searching for &quot;Igor&quot;, I found it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/gatsby/igor.png&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We just learned how to create a source plugin and prerender comments on a Gatsby site!&lt;/p&gt;
&lt;p&gt;I&apos;ve been a huge Gatsby fan ever since it came out, and I&apos;ve really been enjoying how customizable these jam stack setups are.&lt;/p&gt;
&lt;p&gt;If you&apos;re running a Gatsby website with some engagement and you&apos;ve rolled your own commenting system, it wouldn&apos;t be a bad idea to improve your website&apos;s visibility this way.&lt;/p&gt;
&lt;h2 id=&quot;Resources&quot; style=&quot;position:relative;&quot;&gt;Resources&lt;a href=&quot;#Resources&quot; aria-label=&quot;Resources permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Check out the following resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.netlify.com/blog/2016/11/22/prerendering-explained/&quot;&gt;Netlify - &quot;Prerendering Explained&quot;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/stemmlerjs/khalilstemmler-website-2019&quot;&gt;The source code for this blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gatsbyjs.org/blog/2019-08-27-roll-your-own-comment-system/&quot;&gt;Tania&apos;s initial guide, &quot;Roll Your Own Comment System&quot;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gatsbyjs.org/docs/naming-a-plugin/&quot;&gt;Gatsby - Naming a Plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gatsbyjs.org/docs/creating-a-source-plugin/&quot;&gt;Gatsby - Creating a Source Plugin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[How to Learn Software Design and Architecture | The  Full-stack Software Design & Architecture Map]]></title><description><![CDATA[You ever think about what it took for some of the world's most skilled developers to learn how to build systems within companies like Uber…]]></description><link>https://khalilstemmler.com/articles/software-design-architecture/full-stack-software-design/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/software-design-architecture/full-stack-software-design/</guid><pubDate>Sat, 28 Sep 2019 15:04:10 GMT</pubDate><content:encoded>&lt;!-- &lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Update (March 18th, 2024)&lt;/b&gt;: It&apos;s been about 5 years since I first wrote this article here, and - man, oh man. Basically, everything has changed. &lt;br/&gt;&lt;br/&gt;Allow me to explain.&lt;/br&gt;&lt;br/&gt;In 2019, I was knee-deep into trying to find the answer to the question of &quot;how can I learn to write scalable, testable code&quot;? That journey took me into every possible conceivable rabbit hole I could find — studying &amp; practicing the techniques from every programming book I could get my hands on (while asking for guidance from the authors on Twitter). &lt;br&gt;&lt;/br&gt;During this time, I was distilling everything behind me and putting it into the &lt;i&gt;now-extremely-lengthy-soon-to-get-cut-down-and-split-into-other-books&lt;/i&gt; called, solidbook.io. &lt;/br&gt;&lt;br/&gt;Upon finally coming to a conclusion — a resolution to this 7-year long question — I realized the path I took was a &lt;i&gt;really long one&lt;/i&gt; with a bunch of important stuff missing; for example, one &lt;i&gt;last things I learned&lt;/i&gt; was perhaps &lt;b&gt;the most important&lt;/b&gt;: testing. &lt;br/&gt;&lt;br/&gt; I then started to wonder if there was a better way for developers to walk this path. I then started the &lt;i&gt;Software Essentialist Mentorship Program&lt;/i&gt; to see coach developers &amp; see if I could create a better vehicle. &lt;br/&gt;&lt;br/&gt;&lt;b&gt;The 5 Phases of Craftship&lt;/b&gt;: Eventually, after coaching devs to new heights &amp; opportunities, reflecting on my own path, and learning from other developers in our wonderful little &lt;a href=&quot;https://discord.gg/tRz7FfSMY4&quot; target=&quot;blank&quot;&gt;essentialist.dev&lt;/a&gt; Discord community, I learned that there were about &lt;b&gt;5 distinct phases&lt;/b&gt; that all developers tend to go through on their paths to becoming pragmatic, Value-focused developers. These are devs that know the important stuff, know when to follow the rules, when to break the rules, and how to write code that gets better instead of worse over time. Today, the 5 phases make up the bulk of &lt;a href=&quot;https://www.essentialist.dev/the-software-essentialist&quot;&gt;The Software Essentialist&lt;/a&gt; course and the mentorship program. &lt;br/&gt;&lt;br/&gt;&lt;img src=&quot;https://kajabi-storefronts-production.kajabi-cdn.com/kajabi-storefronts-production/file-uploads/site/2147638698/images/bc6a133-e82b-bdc-0d4b-35b273657cd6_76c9866e-be5b-49d3-a083-8acb177ebfdc.png&quot;/&gt; My recommendation is this: if you&apos;re serious about leveling up &amp; learning how to master the stuff that matters - AND you don&apos;t feel like spending 7 years to figure it out, I&apos;ve created a free guide called &quot;An Introduction to the 5 Phases of Craftship&quot;. It will help you know exactly where you&apos;re at now, and what you should focus on next. &lt;br/&gt;&lt;br/&gt;&lt;a href=&quot;https://www.essentialist.dev/offers/hN4GMJcp&quot;&gt;You can get it for free here&lt;/a&gt;. &lt;br/&gt;&lt;br/&gt;&lt;b&gt;How to view &lt;i&gt;this&lt;/i&gt; article (divergence vs. convergence)&lt;/b&gt;: Anytime you&apos;re on a path to achieving any goal, you&apos;re going to be playing a game of &lt;i&gt;Divergence&lt;/i&gt; and &lt;i&gt;Convergence&lt;/i&gt;. This is expanding &amp; contracting. Taking in information &amp; distilling information. Well, this article below - treat this as a point I was at in my &lt;b&gt;Divergence Phase&lt;/b&gt;. A point in which I still had a lot of cutting to do. There&apos;s a lot of value here, still. In terms of gaining clarity on the &lt;b&gt;unknown unknowns&lt;/b&gt;, yes! But ultimately, information needs to get acted upon. So that&apos;s why I recommend a Straight-Line through the 5 Phases to make progress faster.&lt;br/&gt;&lt;br/&gt;Thanks for reading, y&apos;all. To Mastery.&lt;/p&gt;

&lt;br/&gt; --&gt;
&lt;p class=&quot;special-quote&quot;&gt;Translated by readers to: &lt;a target=&quot;_blank&quot; href=&quot;https://qiita.com/ROPITAL/items/165bef33492ba27cfbf7&quot;&gt;Japanese (日本語)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You ever think about what it took for some of the world&apos;s most skilled developers to learn how to build systems within companies like Uber, YouTube, Facebook, or Github?&lt;/p&gt;
&lt;p&gt;It&apos;s crazy to me to consider the fact that Facebook was once an empty text file on someone&apos;s computer, and now it&apos;s this gargantuan company that has dipped it&apos;s toes into just about everything, and has personally impacted over &lt;a href=&quot;https://zephoria.com/top-15-valuable-facebook-statistics/&quot;&gt;1.59 billion people&lt;/a&gt; worldwide.&lt;/p&gt;
&lt;p&gt;As a junior, self-taught developer or even intermediate developer, the roadmap to continued growth towards actually learning how to design &lt;em&gt;clean&lt;/em&gt; and &lt;em&gt;scalable&lt;/em&gt; systems seems kind of daunting.  &lt;/p&gt;
&lt;p&gt;For a lot of us, our projects die after one or two iterations because the code turns into an unmaintainable mess.&lt;/p&gt;
&lt;p&gt;So where do we even &lt;em&gt;start&lt;/em&gt; in order to learn how to improve our designs?&lt;/p&gt;
&lt;p&gt;The truth is: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Software design and architecture is a &lt;em&gt;huge&lt;/em&gt; topic&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Understanding how to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Architect a system to serve the needs of its users&lt;/li&gt;
&lt;li&gt;Write code that&apos;s easy to change&lt;/li&gt;
&lt;li&gt;Write code that&apos;s easy to maintain&lt;/li&gt;
&lt;li&gt;Write code that&apos;s easy to test&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;... is &lt;em&gt;very&lt;/em&gt; hard. The breadth of learning required is just so large.&lt;/p&gt;
&lt;p&gt;And even though you know how to write code to make things work at least &lt;em&gt;once&lt;/em&gt;, the bigger challenge is to figure out how to write code that makes it easy to change in order to &lt;em&gt;keep up with the current requirements&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;But again, where to start?...&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Anytime I&apos;m faced with a complex problem, I go back to &lt;a href=&quot;https://jamesclear.com/first-principles&quot;&gt;first principles&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;First-Principles&quot; style=&quot;position:relative;&quot;&gt;First Principles&lt;a href=&quot;#First-Principles&quot; aria-label=&quot;First Principles permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First principles is the most effective way to break down problems. &lt;/p&gt;
&lt;p&gt;It works by deconstructing a problem all the way down to the &lt;strong&gt;atomic level&lt;/strong&gt; where we can&apos;t deconstruct it anymore, and then reconstructing a solution from the parts that we&apos;re absolutely sure are true.&lt;/p&gt;
&lt;p&gt;So let&apos;s apply it to software by first stating the goal.&lt;/p&gt;
&lt;p&gt;What is the primary goal of software?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The goal of software is to &lt;em&gt;continually&lt;/em&gt; &lt;strong&gt;produce something that satisfies the needs of its users&lt;/strong&gt;, while minimizing the effort it takes to do so.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I fought with coming up with the best definition for a long time, and I&apos;m prepared to argue with you about why I think that&apos;s accurate.&lt;/p&gt;
&lt;p&gt;Software that doesn&apos;t serve the needs of its users, simply isn&apos;t good software.&lt;/p&gt;
&lt;p&gt;And since the needs of our users changes often, it&apos;s important to make sure that software &lt;strong&gt;was designed in order to be changed&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If software cannot be changed (easily), that &lt;u&gt;makes it bad software&lt;/u&gt;, because it prevents us from satisfying the &lt;em&gt;current&lt;/em&gt; needs of our users.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;We&apos;ve established that design matters, and it&apos;s important to learn how to produce well-designed software, but it can be a long road.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;
In this article, I&apos;d like to present to you what I believe are the concrete pillars of software design and architecture. 
&lt;/p&gt;
&lt;h2 id=&quot;The-stack&quot; style=&quot;position:relative;&quot;&gt;The stack&lt;a href=&quot;#The-stack&quot; aria-label=&quot;The stack permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before I show you the map, let me show you the &lt;em&gt;stack&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Similar to something like the &lt;a href=&quot;https://en.wikipedia.org/wiki/OSI_model&quot;&gt;OSI Model&lt;/a&gt;, each layer builds on top of the foundation of the previous one.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/6892666/65833569-bb34fc00-e29f-11e9-8516-79cbd9f8f07b.png&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;The software design and architecture stack shows all of the layers of software design, from the most high-level concepts to the most low-level details.&lt;/p&gt;
&lt;p&gt;In the stack, I&apos;ve included examples to &lt;em&gt;some&lt;/em&gt; of the most important concepts at that layer, but not all (because there are way too many).&lt;/p&gt;
&lt;p&gt;Now, check out the map. While I think the stack is good to see the bigger picture, the map is a little bit more detailed, and as a result, I think it&apos;s more useful.&lt;/p&gt;
&lt;h2 id=&quot;The-map&quot; style=&quot;position:relative;&quot;&gt;The map&lt;a href=&quot;#The-map&quot; aria-label=&quot;The map permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p class=&quot;special-quote&quot;&gt;To avoid running up my bandwidth, I reduced the quality of the map shown on site. If you&apos;d like to get a high-quality png, you can find that up on my &lt;a href=&quot;https://github.com/stemmlerjs/software-design-and-architecture-roadmap&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Below is the map for software design and architecture.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/6892666/65896069-834eb700-e37a-11e9-95be-7ae2300d5d50.png&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;Stage-1-Clean-code&quot; style=&quot;position:relative;&quot;&gt;Stage 1: Clean code&lt;a href=&quot;#Stage-1-Clean-code&quot; aria-label=&quot;Stage 1 Clean code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The very first step towards creating long-lasting software is figuring out how to write &lt;strong&gt;clean code&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;If you ask anyone what they think constitutes &lt;em&gt;clean code&lt;/em&gt;, you&apos;ll probably get a different answer every time. A lot of times, you&apos;ll hear that &lt;em&gt;clean code&lt;/em&gt; is code that is easy to understand and change. At the low-level, this manifests in a few design choices like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;being consistent&lt;/li&gt;
&lt;li&gt;preferring meaningful variable, method and class names over writing comments&lt;/li&gt;
&lt;li&gt;ensuring code is indented and spaced properly&lt;/li&gt;
&lt;li&gt;ensuring all of the tests can run&lt;/li&gt;
&lt;li&gt;writing pure functions with no side effects&lt;/li&gt;
&lt;li&gt;not passing null &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These may seem like small things, but think of it like a game of Jenga. In order to keep the structure of our project stable over time, things like indentation, small classes and methods, and meaningful names, pay off a lot in the long run. &lt;/p&gt;
&lt;p&gt;If you ask me, this aspect of &lt;em&gt;clean code&lt;/em&gt; is about having good &lt;strong&gt;coding conventions&lt;/strong&gt; and following them. &lt;/p&gt;
&lt;p&gt;I belive that&apos;s only &lt;em&gt;one&lt;/em&gt; aspect of writing &lt;em&gt;clean code&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;My definitive explanation of clean code consists of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🧠 Your developer mindset (empathy, craftsmanship, growth mindset, design thinking)&lt;/li&gt;
&lt;li&gt;⚙️ Your coding conventions (naming things, refactoring, testing, etc)&lt;/li&gt;
&lt;li&gt;🤹🏼 Your skills &amp;#x26; knowledge (of patterns, principles, and how to avoid code smells and anti-patterns)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Getting into the right mindset is incredibly important if you want to write clean code. One requirement is that you should care enough to learn about the business you&apos;re writing code within. If we don&apos;t care about the domain enough to understand it, then how can we be sure we&apos;re using &lt;strong&gt;good names&lt;/strong&gt; to represent domain concepts? How can we be sure that we&apos;ve accurately captured the functional requirements? &lt;/p&gt;
&lt;p&gt;If we don&apos;t care about the code that we&apos;re writing, it&apos;s a lot less likely that we&apos;re going to implement essential coding conventions, have meaningful discussions, and ask for feedback on our solutions.&lt;/p&gt;
&lt;p&gt;We often think that code is solely written to serve the needs of the &lt;em&gt;end user&lt;/em&gt;, but we forget the &lt;strong&gt;other people we write code for&lt;/strong&gt;: us, our teammates, and the project&apos;s future maintainers. Having an understanding of the principles of &lt;em&gt;design&lt;/em&gt; and how human psychology decides what is &lt;em&gt;good&lt;/em&gt; and &lt;em&gt;bad&lt;/em&gt; design, will help us write better code.&lt;/p&gt;
&lt;p&gt;So essentially, the best word that describes this step of your journey? &lt;strong&gt;Empathy&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Once we&apos;ve got that down, learn the &lt;em&gt;tricks of the trade&lt;/em&gt; and continue to improve them them over time by improving your knowledge of the essential software development patterns and principles.&lt;/p&gt;
&lt;h3 id=&quot;Learning-resources&quot; style=&quot;position:relative;&quot;&gt;Learning resources&lt;a href=&quot;#Learning-resources&quot; aria-label=&quot;Learning resources permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Clean Code, by Robert C. Martin&lt;/li&gt;
&lt;li&gt;Refactoring, by Martin Fowler (2nd edition)&lt;/li&gt;
&lt;li&gt;The Pragmatic Programmer, by Andy Hunt and Dave Thomas&lt;/li&gt;
&lt;li&gt;The Design of Everyday Things, by Don Norman&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The best resource to learn how to write clean code is Uncle Bob&apos;s book, &quot;&lt;a href=&quot;https://www.amazon.ca/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882&quot;&gt;Clean Code&lt;/a&gt;&quot;.&lt;/p&gt;
&lt;h2 id=&quot;Stage-2-Programming-Paradigms&quot; style=&quot;position:relative;&quot;&gt;Stage 2: Programming Paradigms&lt;a href=&quot;#Stage-2-Programming-Paradigms&quot; aria-label=&quot;Stage 2 Programming Paradigms permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that we&apos;re writing readable code that&apos;s easy to maintain, it would be a good idea to really understand the 3 major programming paradigms and the way they influence how we write code.&lt;/p&gt;
&lt;p&gt;In Uncle Bob&apos;s book, &quot;&lt;a href=&quot;https://www.amazon.ca/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=asc_df_0132350882/?tag=googleshopc0c-20&amp;#x26;linkCode=df0&amp;#x26;hvadid=292982483438&amp;#x26;hvpos=1o2&amp;#x26;hvnetw=g&amp;#x26;hvrand=13521899336201370454&amp;#x26;hvpone=&amp;#x26;hvptwo=&amp;#x26;hvqmt=&amp;#x26;hvdev=c&amp;#x26;hvdvcmdl=&amp;#x26;hvlocint=&amp;#x26;hvlocphy=9000834&amp;#x26;hvtargid=pla-435472505264&amp;#x26;psc=1&quot;&gt;Clean Architecture&lt;/a&gt;&quot;, he brings attention to the fact that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Object-Oriented Programming is the tool best suited for defining how we cross architectural boundaries with polymorphism and plugins&lt;/li&gt;
&lt;li&gt;Functional programming is the tool we use to push data to the boundaries of our applications&lt;/li&gt;
&lt;li&gt;and Structured programming is the tool we use to write algorithms&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This implies that effective software uses a hybrid all 3 programming paradigms styles at different times.&lt;/p&gt;
&lt;p&gt;While you &lt;em&gt;could&lt;/em&gt; take a strictly functional or strictly object-oriented approach to writing code, understanding where each excels will improve the quality of your designs.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If all you have is a hammer, everything seems like a nail.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;Learning-resources-1&quot; style=&quot;position:relative;&quot;&gt;Learning resources&lt;a href=&quot;#Learning-resources-1&quot; aria-label=&quot;Learning resources 1 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Clean Architecture, by Robert C. Martin&lt;/li&gt;
&lt;li&gt;Domain Modeling Made Functional, by Scott Wlaschin&lt;/li&gt;
&lt;li&gt;Concepts of Programming Languages, Robert W. Sebesta (10th edition)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Stage-3-Object-Oriented-Programming&quot; style=&quot;position:relative;&quot;&gt;Stage 3: Object-Oriented Programming&lt;a href=&quot;#Stage-3-Object-Oriented-Programming&quot; aria-label=&quot;Stage 3 Object Oriented Programming permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It&apos;s important to know how each of the paradigms work and how they urge you to structure the code within them, but with respect to architecture, Object-Oriented Programming is the clear &lt;em&gt;tool for the job&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Not only does Object-Oriented programming enable us to create a &lt;strong&gt;plugin architecture&lt;/strong&gt; and build flexibility into our projects; OOP comes with the 4 principles of OOP (encapsulation, inheritance, polymorhism, and abstraction) that help us create &lt;strong&gt;rich domain models&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Most developers learning Object-Oriented Programming never get to this part: learning how to create a &lt;u&gt;software implementation of the problem domain&lt;/u&gt;, and locating it in the center of a &lt;strong&gt;layered&lt;/strong&gt; web app. &lt;/p&gt;
&lt;p&gt;Functional programming can seem like the means to all ends in this scenario, but  I&apos;d recommend getting acquainted with model-driven design and &lt;a href=&quot;https://khalilstemmler.com/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design&lt;/a&gt; to understand the bigger picture on how object-modelers are able to encapsulate an entire business in a zero-dependency domain model.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Why is that a huge deal?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It&apos;s huge because if you can create a mental-model of a business, you can create a software implementation of that business.&lt;/p&gt;
&lt;h3 id=&quot;Learning-resources-2&quot; style=&quot;position:relative;&quot;&gt;Learning resources&lt;a href=&quot;#Learning-resources-2&quot; aria-label=&quot;Learning resources 2 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Object-Design Style Guide, by Matthias Noback&lt;/li&gt;
&lt;li&gt;Clean Architecture, by Robert C. Martin&lt;/li&gt;
&lt;li&gt;Domain-Driven Design, by Eric Evans&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Stage-4-Design-Principles&quot; style=&quot;position:relative;&quot;&gt;Stage 4: Design Principles&lt;a href=&quot;#Stage-4-Design-Principles&quot; aria-label=&quot;Stage 4 Design Principles permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At this point, you&apos;re understanding that Object-Oriented Programming is very useful for encapsulating rich domain models and solving the &lt;a href=&quot;https://khalilstemmler.com/wiki/3-categories-of-hard-software-problems/&quot;&gt;3rd type of &quot;Hard Software Problems&quot;- Complex Domains&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But OOP can introduce some design challenges. &lt;/p&gt;
&lt;p&gt;When should I use composition?&lt;/p&gt;
&lt;p&gt;When should I use inheritance?&lt;/p&gt;
&lt;p&gt;When should I use an abstract class?&lt;/p&gt;
&lt;p&gt;Design principles are really well-established and battle-tested object-oriented best practices that you use as railguards.&lt;/p&gt;
&lt;p&gt;Some examples of common design principles you should familiarize yourself with are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Composition over inheritance&lt;/li&gt;
&lt;li&gt;Encapsulate what varies&lt;/li&gt;
&lt;li&gt;Program against abstractions, not concretions&lt;/li&gt;
&lt;li&gt;The hollywood principle: &quot;Don&apos;t call us, we&apos;ll call you&quot;&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://khalilstemmler.com/articles/solid-principles/solid-typescript/&quot;&gt;SOLID principles&lt;/a&gt;, especially the &lt;a href=&quot;https://khalilstemmler.com/articles/solid-principles/single-responsibility/&quot;&gt;Single responsibility principle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;DRY (Do Not Repeat Yourself)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/wiki/yagni/&quot;&gt;YAGNI (You Aren&apos;t Gonna Need It)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Make sure to come to your &lt;em&gt;own&lt;/em&gt; conclusions, though. Don&apos;t just follow what someone else says you should do. Make sure that it makes sense to you.&lt;/p&gt;
&lt;h3 id=&quot;Learning-resources-3&quot; style=&quot;position:relative;&quot;&gt;Learning resources&lt;a href=&quot;#Learning-resources-3&quot; aria-label=&quot;Learning resources 3 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Head First Design Patterns, by various authors&lt;/li&gt;
&lt;li&gt;GoF Design Patterns, by various authors&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Stage-5-Design-Patterns&quot; style=&quot;position:relative;&quot;&gt;Stage 5: Design Patterns&lt;a href=&quot;#Stage-5-Design-Patterns&quot; aria-label=&quot;Stage 5 Design Patterns permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Just about every problem in software has been categorized and solved already. We call these patterns: design patterns, actually.&lt;/p&gt;
&lt;p&gt;There are 3 categories of design patterns: &lt;strong&gt;creational&lt;/strong&gt;, &lt;strong&gt;structural&lt;/strong&gt;, and &lt;strong&gt;behaviour&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Creational&quot; style=&quot;position:relative;&quot;&gt;Creational&lt;a href=&quot;#Creational&quot; aria-label=&quot;Creational permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Creational patterns are patterns that control how objects are created.&lt;/p&gt;
&lt;p&gt;Examples of creational patterns include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Singleton pattern&lt;/strong&gt;, for ensuring only a single instance of a class can exist&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Abstract Factory pattern&lt;/strong&gt;, for creating an instance of several families of classes&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Prototype pattern&lt;/strong&gt;, for starting out with an instance that is cloned from an existing one&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Structural&quot; style=&quot;position:relative;&quot;&gt;Structural&lt;a href=&quot;#Structural&quot; aria-label=&quot;Structural permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Structural patterns are patterns that simplify how we define relationships between components.&lt;/p&gt;
&lt;p&gt;Examples of structural design patterns include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Adapter pattern&lt;/strong&gt;, for creating an interface to enable classes that normally can&apos;t work together, to work together. &lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Bridge pattern&lt;/strong&gt;, for splitting a class that should actually be one or more, into a set of classes that belong to a hierarchy, enabling the implementations to be developed independently of each other.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Decorator pattern&lt;/strong&gt;, for adding responsibilities to objects dynamically.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Behavioural&quot; style=&quot;position:relative;&quot;&gt;Behavioural&lt;a href=&quot;#Behavioural&quot; aria-label=&quot;Behavioural permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Behavioural patterns are common patterns for facilitating elegant communication between objects.&lt;/p&gt;
&lt;p&gt;Examples of behavioural patterns are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Template pattern&lt;/strong&gt;, for deferring the exact steps of an algorithm to a subclass.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Mediator pattern&lt;/strong&gt;, for defining the exact communication channels allowed between classes. &lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Observer pattern&lt;/strong&gt;, for enabling classes to subscribe to something of interest, and to be notified when a change occurred.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;Design-pattern-criticisms&quot; style=&quot;position:relative;&quot;&gt;Design pattern criticisms&lt;a href=&quot;#Design-pattern-criticisms&quot; aria-label=&quot;Design pattern criticisms permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Design patterns are great and all, but sometimes they can an additional complexity to our designs. It&apos;s important to remember YAGNI and attempt to keep our designs as simple as possible. Only use design patterns when you&apos;re really sure you need them. You&apos;ll know when you will.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;If we know what each of these patterns are, when to use them, and when to &lt;em&gt;not even bother&lt;/em&gt; using them, we&apos;re in good shape to begin to understand how to architect larger systems.&lt;/p&gt;
&lt;p&gt;The reason behind that is because &lt;strong&gt;architectural patterns are just design patterns blown-up in scale to the high-level&lt;/strong&gt;, where design patterns are low-level implementations (closer to classes and functions).&lt;/p&gt;
&lt;h3 id=&quot;Learning-resources-4&quot; style=&quot;position:relative;&quot;&gt;Learning resources&lt;a href=&quot;#Learning-resources-4&quot; aria-label=&quot;Learning resources 4 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Head First Design Patterns, by various authors&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Stage-6-Architectural-Principles&quot; style=&quot;position:relative;&quot;&gt;Stage 6: Architectural Principles&lt;a href=&quot;#Stage-6-Architectural-Principles&quot; aria-label=&quot;Stage 6 Architectural Principles permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now we&apos;re at a higher level of thinking beyond the class level.&lt;/p&gt;
&lt;p&gt;We now understand that the decisions we make towards organzing and building relationships between components at the high-level and the low-level, will have a significant impact on the maintainability, flexibility, and testability of our project.&lt;/p&gt;
&lt;p&gt;Learn the guiding principles that helps you build in the flexibility that your codebase needs in order to be able to react to new features and requirements, with as little effort as possible.&lt;/p&gt;
&lt;p&gt;Here&apos;s what I&apos;d recommend learning right off the bat:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Component design principles: &lt;a href=&quot;https://khalilstemmler.com/wiki/stable-abstraction-principle/&quot;&gt;The Stable Abstraction Principle&lt;/a&gt;, &lt;a href=&quot;https://khalilstemmler.com/wiki/stable-dependency-principle/&quot;&gt;The Stable Dependency Principle&lt;/a&gt;, and The Acyclic Dependency Principle, for how to organize components, their dependencies, when to couple them, and the implications of accidentally creating dependency cycles and relying on unstable components.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;Policy vs. Detail&lt;/a&gt;, for understanding how to separate the rules of your application from the implementation details.&lt;/li&gt;
&lt;li&gt;Boundaries, and how to identify the &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;subdomains&lt;/a&gt; that the features of your application belongs within.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Uncle Bob discovered and originally documented many of these principles, so the best resource to learn about this is again, &quot;&lt;a href=&quot;https://www.amazon.ca/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=asc_df_0132350882/?tag=googleshopc0c-20&amp;#x26;linkCode=df0&amp;#x26;hvadid=292982483438&amp;#x26;hvpos=1o2&amp;#x26;hvnetw=g&amp;#x26;hvrand=13521899336201370454&amp;#x26;hvpone=&amp;#x26;hvptwo=&amp;#x26;hvqmt=&amp;#x26;hvdev=c&amp;#x26;hvdvcmdl=&amp;#x26;hvlocint=&amp;#x26;hvlocphy=9000834&amp;#x26;hvtargid=pla-435472505264&amp;#x26;psc=1&quot;&gt;Clean Architecture&lt;/a&gt;&quot;.&lt;/p&gt;
&lt;h3 id=&quot;Learning-resources-5&quot; style=&quot;position:relative;&quot;&gt;Learning resources&lt;a href=&quot;#Learning-resources-5&quot; aria-label=&quot;Learning resources 5 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Clean Architecture, by Robert C. Martin&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Stage-7-Architectural-Styles&quot; style=&quot;position:relative;&quot;&gt;Stage 7: Architectural Styles&lt;a href=&quot;#Stage-7-Architectural-Styles&quot; aria-label=&quot;Stage 7 Architectural Styles permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Architecture is about the stuff that matters.&lt;/p&gt;
&lt;p&gt;It&apos;s about identifying what a system needs in order for it to be successful, and then &lt;u&gt;stacking the odds of success&lt;/u&gt; by choosing the architecture that best fits the requirements.&lt;/p&gt;
&lt;p&gt;For example, a system that has a lot of &lt;strong&gt;business logic complexity&lt;/strong&gt; would benefit from using a &lt;strong&gt;layered architecture&lt;/strong&gt; to encapsulate that complexity.&lt;/p&gt;
&lt;p&gt;A system like Uber needs to be able to handle a lot of &lt;strong&gt;real time-events&lt;/strong&gt; at once and update drivers&apos; locations, so &lt;strong&gt;publish-subscribe&lt;/strong&gt; style architecture might be most effective.&lt;/p&gt;
&lt;p&gt;I&apos;ll repeat myself here because it&apos;s important to note that the 3 categories of architectural styles are similar to the 3 categories of design patterns, because &lt;strong&gt;architectural styles are design patterns at the high-level&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Structrual&quot; style=&quot;position:relative;&quot;&gt;Structrual&lt;a href=&quot;#Structrual&quot; aria-label=&quot;Structrual permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Projects with &lt;em&gt;varying levels&lt;/em&gt; of components and wide-ranging functionality will either benefit or suffer from adopting a structural architecture.&lt;/p&gt;
&lt;p&gt;Here are a few examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Component-based&lt;/strong&gt; architectures emphasize &lt;u&gt;separation of concerns&lt;/u&gt; between the &lt;em&gt;individual components&lt;/em&gt; within a system. Think &lt;strong&gt;Google&lt;/strong&gt; for a sec. Consider how many applications they have within their enterprise (Google Docs, Google Drive, Google Maps, etc). For platforms with lots of functionality, component-based architectures divide the concerns into loosely coupled independent components. This is a &lt;em&gt;horizontal&lt;/em&gt; separation. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monolithic&lt;/strong&gt; means that the application is combined into a single platform or program, deployed altogether. &lt;em&gt;Note: You can have a component-based AND monolithic  architecture if you separate your applications properly, yet deploy it all as one piece&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Layered&lt;/strong&gt; architectures separate the concerns &lt;em&gt;vertically&lt;/em&gt; by cutting software into infrastructure, application, and domain layers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://khalilstemmler.com/img/blog/software-architecture-design/app-logic-layers.svg&quot; alt=&quot;Clean Architecture&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An example of cutting the concerns of an application &lt;em&gt;vertically&lt;/em&gt; by using a layered architecture. Read &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/organizing-app-logic/&quot;&gt;here&lt;/a&gt; for more information on how to do this.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;Messaging&quot; style=&quot;position:relative;&quot;&gt;Messaging&lt;a href=&quot;#Messaging&quot; aria-label=&quot;Messaging permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Depending on your project, messaging might be a really important component to the success of the system. For projects like this, message-based architectures build on top of functional programming principles and behavioural design patterns like the observer pattern.&lt;/p&gt;
&lt;p&gt;Here are a few examples of message-based architectural styles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Event-Driven&lt;/strong&gt; architectures view all signficant changes to state as events. For example, within a &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;vinyl-trading app&lt;/a&gt;, a offer&apos;s state might change from &quot;pending&quot; to &quot;accepted&quot; when both parties agreee on the trade. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Publish-subscribe&lt;/strong&gt; architectures build on top of the Observer design pattern by making it the primary communication method between the system itself, end-users / clients, and others systems and components.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Distributed&quot; style=&quot;position:relative;&quot;&gt;Distributed&lt;a href=&quot;#Distributed&quot; aria-label=&quot;Distributed permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A distributed architecture simply means that the components of the system are deployed separately and operate by communicating over a network protocol. Distributed systems can be very effective for scaling throughput, scaling teams, and delegating (potentially expensive tasks or) responsibility to other components.&lt;/p&gt;
&lt;p&gt;A few examples of distributed architectural styles are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Client-server&lt;/strong&gt; architecture. One of the most common architectures, where we divide the work to be done between the client (presentation) and the server (business logic). &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Peer-to-peer&lt;/strong&gt; architectures distribute application-layer tasks between equally-privileged participants, forming a peer-to-peer network. &lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Learning-resources-6&quot; style=&quot;position:relative;&quot;&gt;Learning resources&lt;a href=&quot;#Learning-resources-6&quot; aria-label=&quot;Learning resources 6 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Clean Architecture, by Robert C. Martin&lt;/li&gt;
&lt;li&gt;Software Architect&apos;s Handbook, by Joseph Ingeno &lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Stage-8-Architectural-Patterns&quot; style=&quot;position:relative;&quot;&gt;Stage 8: Architectural Patterns&lt;a href=&quot;#Stage-8-Architectural-Patterns&quot; aria-label=&quot;Stage 8 Architectural Patterns permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Architectural &lt;em&gt;patterns&lt;/em&gt; explain in greater tactical detail how to actually implement one of those architectural &lt;em&gt;styles&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Here are a couple of examples of architectural patterns and the styles that they inherit from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design&lt;/a&gt;&lt;/strong&gt; is an approach to software development against really complex problem domains. For DDD to be most successful, we need to implement a &lt;strong&gt;layered architecture&lt;/strong&gt; in order to separate the concerns of a domain model from the infrastrural details that makes the application actually run, like databases, webservers, caches, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Model-View Controller&lt;/strong&gt; is probably the &lt;u&gt;most well-known&lt;/u&gt; architectural pattern for developing user interface-based applications. It works by dividing the app into 3 components: model, view, and controller. MVC is incredibly useful when you&apos;re first starting out, and it helps you piggyback towards other architectures, but there hit&apos;s a point when we realize &lt;a href=&quot;https://khalilstemmler.com/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;MVC isn&apos;t enough&lt;/a&gt; for problems with lots of business logic.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Event sourcing&lt;/strong&gt; is a functional approach where we  store only the transactions, and never the state. If we ever need the state, we can apply all the transactions from the beginning of time.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Learning-resource&quot; style=&quot;position:relative;&quot;&gt;Learning resource&lt;a href=&quot;#Learning-resource&quot; aria-label=&quot;Learning resource permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Domain-Driven Design, by Eric Evans&lt;/li&gt;
&lt;li&gt;Implementing Domain-Driven Design, by Vaughn Vernon&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Stage-9-Enterprise-patterns&quot; style=&quot;position:relative;&quot;&gt;Stage 9: Enterprise patterns&lt;a href=&quot;#Stage-9-Enterprise-patterns&quot; aria-label=&quot;Stage 9 Enterprise patterns permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Any architectural pattern you choose will introduce a number of constructs and technical jargon to familiarize yourself with and decide on whether it&apos;s worth the effort to use or not.&lt;/p&gt;
&lt;p&gt;Taking an example that many of us know, in &lt;strong&gt;MVC&lt;/strong&gt;, the &lt;em&gt;view&lt;/em&gt; holds all the presentation layer code, the &lt;em&gt;controller&lt;/em&gt; is translates commands and queries from the &lt;em&gt;view&lt;/em&gt; into requests that are handled by the &lt;em&gt;model&lt;/em&gt; and returned by the &lt;em&gt;controller&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Where in the Model (M) do we handle these things?:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;validation logic&lt;/li&gt;
&lt;li&gt;invariant rules&lt;/li&gt;
&lt;li&gt;domain events&lt;/li&gt;
&lt;li&gt;use cases&lt;/li&gt;
&lt;li&gt;complex queries&lt;/li&gt;
&lt;li&gt;and business logic&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If we simply use an ORM (object-relational mapper) like &lt;a href=&quot;&quot;&gt;Sequelize&lt;/a&gt; or &lt;a href=&quot;&quot;&gt;TypeORM&lt;/a&gt; as the &lt;em&gt;model&lt;/em&gt;, all that important stuff to gets left to interpretation on where it should go, and it finds itself in some unspecified layer between (what should be a rich) &lt;em&gt;model&lt;/em&gt; and the &lt;em&gt;controller&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.freecodecamp.org/news/content/images/2019/10/mvc-2.svg&quot; alt=&quot;mvc-2&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Taken from &quot;3.1 - Slim (Logic-less) models&quot; in &lt;a href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If there&apos;s something I&apos;ve learned so far in my journey going beyond MVC, it&apos;s that &lt;strong&gt;there is a construct for everything&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For each of those things that MVC fails to address, in &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design specifically&lt;/a&gt;, there exist several &lt;strong&gt;enterprise patterns&lt;/strong&gt; to solve them. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/entities/&quot;&gt;Entities&lt;/a&gt;&lt;/strong&gt; describe models that have an identity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/typescript-value-object/&quot;&gt;Value Objects&lt;/a&gt;&lt;/strong&gt; are models that have no identity, and can be used in order to encapsulate validation logic.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/chain-business-logic-domain-events/&quot;&gt;Domain Events&lt;/a&gt;&lt;/strong&gt; are events that signify some relevant business event occurring, and can be subscribed to from other components.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Depending on the architectural style you&apos;ve chosen, there are going to be &lt;em&gt;a ton&lt;/em&gt; of other enterprise patterns for you to learn in order to implement that pattern to it&apos;s fullest potential. &lt;/p&gt;
&lt;h3 id=&quot;Learning-resources-7&quot; style=&quot;position:relative;&quot;&gt;Learning resources&lt;a href=&quot;#Learning-resources-7&quot; aria-label=&quot;Learning resources 7 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;These are just a few different learning resources mostly focused on Domain-Driven Design and Enteprise Application Architecture. But this is where there is the &lt;em&gt;most&lt;/em&gt; to learn, and where you can &lt;em&gt;dive the deepest&lt;/em&gt; in your learning, because it &lt;u&gt;builds ontop of everything we&apos;ve learned thus far&lt;/u&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Patterns of Enterprise Application Architecture, by Martin Fowler&lt;/li&gt;
&lt;li&gt;Enterprise Integration Patterns, by Gregor Hohpe&lt;/li&gt;
&lt;li&gt;Domain Driven Design, by Eric Evans&lt;/li&gt;
&lt;li&gt;Implementing Domain-Driven Design, by Vaughn Vernon&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Resources--Conclusion&quot; style=&quot;position:relative;&quot;&gt;Resources &amp;#x26; Conclusion&lt;a href=&quot;#Resources--Conclusion&quot; aria-label=&quot;Resources  Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We talk a lot about &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design&lt;/a&gt; on this blog, but &lt;u&gt;there&apos;s a lot readers would benefit from knowing first&lt;/u&gt; (like layered architectures, oop, model-driven design, design principles and patterns) before we dive deep on building rich domain models with TypeScript.&lt;/p&gt;
&lt;div class=&quot;solid-book-cta course-cta special-quote&quot;&gt;
  &lt;div class=&quot;solid-book-logo-container&quot;&gt;
    &lt;img src=&quot;/img/resources/solid-book/book-logo.png&quot;/&gt;
  &lt;/div&gt;
  &lt;p&gt;If you&apos;re looking for a one-stop resource, I just prelaunched &lt;a href=&quot;https://solidbook.io&quot;&gt;solidbook.io - The Software Design &amp; Architecture Handbook&lt;/a&gt;. I teach readers the things that I think they really need to know at each stage in this map in order to produce good software like we discussed in this article. It&apos;s currently on sale until it&apos;s fully complete, but I&apos;m also happy to recommend a couple of other excellent resources that I personally used when I was learning software design and architecture.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;References&quot; style=&quot;position:relative;&quot;&gt;References&lt;a href=&quot;#References&quot; aria-label=&quot;References permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_software_architecture_styles_and_patterns&quot;&gt;Wikipedia: List of architectural styles and patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://herbertograca.com/2017/07/28/architectural-styles-vs-architectural-patterns-vs-design-patterns/&quot;&gt;Architectural styles vs. architectural patterns vs. design patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html&quot;&gt;The Clean Architecture&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Decoupling Logic with Domain Events [Guide] - Domain-Driven Design w/ TypeScript]]></title><description><![CDATA[Introduction When we're working on backend logic, it's not uncommon to eventually find yourself using language like this to describe what…]]></description><link>https://khalilstemmler.com/articles/typescript-domain-driven-design/chain-business-logic-domain-events/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/typescript-domain-driven-design/chain-business-logic-domain-events/</guid><pubDate>Thu, 26 Sep 2019 22:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;course-cta&quot;&gt;
We cover this topic in &lt;a href=&quot;https://www.essentialist.dev/master-the-essentials-of-software-design-with-typescript&quot;&gt;The Software Essentialist&lt;/a&gt; online course. Check it out if you liked this post.
&lt;/p&gt;
&lt;h2 id=&quot;Introduction&quot; style=&quot;position:relative;&quot;&gt;Introduction&lt;a href=&quot;#Introduction&quot; aria-label=&quot;Introduction permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When we&apos;re working on backend logic, it&apos;s not uncommon to eventually find yourself using language like this to describe what should happen.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;When __ happens, then do ___&quot;. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;And &quot;after this, do that&quot;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Or, &quot;after this, &lt;strong&gt;and&lt;/strong&gt; that, and then this... &lt;em&gt;but &lt;u&gt;only&lt;/u&gt; when&lt;/em&gt; &lt;em&gt;this&lt;/em&gt;, do that&quot;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Just all kinds of noise, right?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Chaining logic&lt;/strong&gt; can get really messy. &lt;/p&gt;
&lt;p&gt;Here&apos;s what I mean.&lt;/p&gt;
&lt;p&gt;When someone &lt;strong&gt;registers for an account&lt;/strong&gt; on &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;White Label&lt;/a&gt;, the open-source Vinyl-Trading DDD application I&apos;m building, I want to do several things.&lt;/p&gt;
&lt;p&gt;I want to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create the user&apos;s account&lt;/li&gt;
&lt;li&gt;Uniquely assign that user a default username based on their actual name&lt;/li&gt;
&lt;li&gt;Send a notification to my Slack channel letting me know that someone signed up&lt;/li&gt;
&lt;li&gt;Add that user to my Mailing List&lt;/li&gt;
&lt;li&gt;Send them a Welcome Email&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;... and I&apos;ll probably think of more things later as well. &lt;/p&gt;
&lt;p&gt;How would &lt;em&gt;you&lt;/em&gt; code this up?&lt;/p&gt;
&lt;p&gt;A first approach might be to do all of this stuff in a &lt;code class=&quot;language-text&quot;&gt;UsersService&lt;/code&gt;, because that&apos;s where the &lt;em&gt;main&lt;/em&gt; event (creating the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;) is taking place, right?&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;UsersService.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; SlackService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../notification/services/slack&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; MailchimpService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../marketing/services/mailchimp&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; SendGridService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../notification/services/email&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UsersService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; sequelizeModels&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;constuctor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;sequelizeModels&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sequelizeModels &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; sequelizeModels&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Assign a username (also, might be taken)&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; username &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;firstName&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;lastName&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Create user&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; sequelizeModels&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; username
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Send notification to slack channel&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; SlackService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendNotificatation&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Hey guys, &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;firstName&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;lastName&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; @ &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;email&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; just signed up.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Add user to mailing list&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; MailchimpService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Send a welcome email &lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; welcomeEmailTitle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Welcome to White Label&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; welcomeEmailText &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Hey, welcome to the hottest place to trade vinyl.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; SendGridService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; welcomeEmailTitle&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; welcomeEmailText&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The humanity! You probably feel &lt;a target=&quot;_blank&quot; href=&quot;https://www.youtube.com/watch?v=zhavFPiZXP4&quot;&gt;like this&lt;/a&gt; right now.&lt;/p&gt;
&lt;p&gt;Alright, what&apos;s wrong with this?&lt;/p&gt;
&lt;p&gt;Lots. But the main things are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code class=&quot;language-text&quot;&gt;UsersService&lt;/code&gt; knows too much about things that aren&apos;t related to &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt;. Sending emails and slack messages most likely should belong to the &lt;code class=&quot;language-text&quot;&gt;Notifications&lt;/code&gt; subdomain, while hooking up marketing campaigns using a tool like Mailchimp would make more sense to belong to a &lt;code class=&quot;language-text&quot;&gt;Marketing&lt;/code&gt; subdomain. Currently, we&apos;ve &lt;u&gt;coupled&lt;/u&gt; all of the unrelated side-effects of &lt;code class=&quot;language-text&quot;&gt;createUser&lt;/code&gt; to the &lt;code class=&quot;language-text&quot;&gt;UsersService&lt;/code&gt;. Think about how challenging it will be in order to isolate and &lt;em&gt;test&lt;/em&gt; this class now.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can fix this.&lt;/p&gt;
&lt;p&gt;There&apos;s a design principle out there that&apos;s specifically useful for times like this. &lt;/p&gt;
&lt;div class=&quot;special-quote solid-book-cta&quot;&gt;
  &lt;a href=&quot;https://solidbook.io&quot; class=&quot;solid-book-logo-container&quot;&gt;
    &lt;img src=&quot;/img/resources/solid-book/book-logo.png&quot;/&gt;
  &lt;/a&gt;
  &lt;p&gt;
    &lt;b&gt;Design Principle&lt;/b&gt;: &quot;Strive for loosely coupled design against objects that interact&quot;. - via &lt;a href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt;: The Software Architecture &amp; Design Handbook
  &lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;This decoupling principle is at the heart of lots of one of my favourite libraries, &lt;a href=&quot;https://github.com/ReactiveX/rxjs&quot;&gt;RxJs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The design pattern it&apos;s built on is called the &lt;strong&gt;observer pattern&lt;/strong&gt;. &lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In this article, we&apos;ll learn how to use Domain Events in order to decouple complex business logic. &lt;/p&gt;
&lt;h2 id=&quot;Prerequisites&quot; style=&quot;position:relative;&quot;&gt;Prerequisites&lt;a href=&quot;#Prerequisites&quot; aria-label=&quot;Prerequisites permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In order to get the most out of this guide, you should know the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;What Domain-Driven Design is all about&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Understand the role of &lt;a href=&quot;/articles/typescript-domain-driven-design/entities/&quot;&gt;entities&lt;/a&gt;, &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;value objects&lt;/a&gt;, &lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;aggregates&lt;/a&gt;, and &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;repositories&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;How logically separating your app into &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;Subdomains and Use Cases&lt;/a&gt; helps you to quickly understand where code belongs and enforce architectural boundaries.&lt;/li&gt;
&lt;li&gt;And (optionally), you&apos;ve read the &lt;a href=&quot;/blogs/domain-driven-design/where-do-domain-events-get-dispatched/&quot;&gt;previous article&lt;/a&gt; on Domain Events.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;What-are-Domain-Events&quot; style=&quot;position:relative;&quot;&gt;What are Domain Events?&lt;a href=&quot;#What-are-Domain-Events&quot; aria-label=&quot;What are Domain Events permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every business has key events that are &lt;strong&gt;important&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;In our &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;vinyl-trading application&lt;/a&gt;, within the &lt;code class=&quot;language-text&quot;&gt;vinyl&lt;/code&gt; subdomain, we have events like &lt;code class=&quot;language-text&quot;&gt;VinylCreated&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;VinylUpdated&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;VinylAddedToWishList&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In a job seeking application, we might see events like &lt;code class=&quot;language-text&quot;&gt;JobPosted&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;AppliedToJob&lt;/code&gt;, or &lt;code class=&quot;language-text&quot;&gt;JobExpired&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;Despite the domain that they belong to, when &lt;strong&gt;domain events&lt;/strong&gt; are created and dispatched, they provide the opportunity for &lt;em&gt;other (decoupled) parts&lt;/em&gt; of our application to execute some code after that event.&lt;/p&gt;
&lt;h2 id=&quot;Actors-Commands-Events-and-Subscriptions&quot; style=&quot;position:relative;&quot;&gt;Actors, Commands, Events, and Subscriptions&lt;a href=&quot;#Actors-Commands-Events-and-Subscriptions&quot; aria-label=&quot;Actors Commands Events and Subscriptions permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In order to determine all of the capabilities of an app, an approach is to start by identifying the &lt;strong&gt;actors&lt;/strong&gt;, &lt;strong&gt;commands&lt;/strong&gt;, &lt;strong&gt;events&lt;/strong&gt;, and &lt;strong&gt;responses to those events (subscriptions)&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Actors: &lt;em&gt;Who&lt;/em&gt; or &lt;em&gt;what&lt;/em&gt; is this relevant person (or thing) to the domain? - &lt;code class=&quot;language-text&quot;&gt;Authors&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Editors&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Guest&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Server&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Commands: &lt;em&gt;What&lt;/em&gt; can they do? - &lt;code class=&quot;language-text&quot;&gt;CreateUser&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;DeleteAccount&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;PostArticle&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Event: &lt;em&gt;Past&lt;/em&gt;-tense version of the command (verb) - &lt;code class=&quot;language-text&quot;&gt;UserCreated&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;AccountDeleted&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;ArticlePosted&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Subscriptions: Classes that are interested in the domain event that want to be notified when they occurred - &lt;code class=&quot;language-text&quot;&gt;AfterUserCreated&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;AfterAccountDeleted&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;AfterArticlePosted&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the DDD-world, there&apos;s a fun activity you can do with your team to discover all of these. It&apos;s called &lt;a href=&quot;https://philippe.bourgau.net/how-to-use-event-storming-to-introduce-domain-driven-design/&quot;&gt;Event Storming&lt;/a&gt; and it involves using sticky notes in order to discover the business rules.&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; src=&quot;https://proophsoftware.github.io/fee-office/ddd/img/event_storming_colors.png&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;Each sticky note color represents a different DDD concept.&lt;/p&gt;
&lt;p&gt;At the end of this process, depending on the size of your company, you&apos;ll probably end up with a huge board full of stickies.&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; src=&quot;/img/blog/domain-events/board.png&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;Someone&apos;s productive Event Storming session.&lt;/p&gt;
&lt;p&gt;At this point, we&apos;ll probably have a good understanding of who does what, what the commands are, what the policies are the govern when someone can perform a particular command, and what happens in response to those commands as subscriptions to domain events.&lt;/p&gt;
&lt;p&gt;Let&apos;s apply that to our &lt;code class=&quot;language-text&quot;&gt;CreateUser&lt;/code&gt; command at a smaller scale.&lt;/p&gt;
&lt;h2 id=&quot;Uncovering-the-business-rules&quot; style=&quot;position:relative;&quot;&gt;Uncovering the business rules&lt;a href=&quot;#Uncovering-the-business-rules&quot; aria-label=&quot;Uncovering the business rules permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Alright, so &lt;strong&gt;any anonymous user&lt;/strong&gt; is able to create an account. So an &lt;code class=&quot;language-text&quot;&gt;anonymous user&lt;/code&gt; should be able to execute the &lt;code class=&quot;language-text&quot;&gt;CreateUser&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;subdomain&lt;/strong&gt; this command belongs to would be the &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt; subdomain.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Don&apos;t remember how &lt;i&gt;subdomains&lt;/i&gt; work? &lt;/b&gt; Read &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;this article&lt;/a&gt; first.&lt;/p&gt;
&lt;p&gt;OK. Now, what are the other things we want to happen &lt;em&gt;in response&lt;/em&gt; to the &lt;code class=&quot;language-text&quot;&gt;UserCreated&lt;/code&gt; event that would get created and then dispatched?&lt;/p&gt;
&lt;p&gt;Let&apos;s look at the code again.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;UsersService.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; SlackService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../notification/services/slack&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; MailchimpService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../marketing/services/mailchimp&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; SendGridService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../notification/services/email&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UsersService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; sequelizeModels&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;constuctor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;sequelizeModels&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sequelizeModels &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; sequelizeModels&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Create user (this is ALL that should be here)&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; sequelizeModels&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Subscription side-effect (Users subdomain): Assign user username&lt;/span&gt;
      
      &lt;span class=&quot;token comment&quot;&gt;// Subscription side-effect (Notifications subdomain): Send notification to slack channel&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Subscription side-effect (Marketing subdomain): Add user to mailing list&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Subscription side-effect (Notifications subdomain): Send a welcome email &lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Alright, so we have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Subscription side-effect #1&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt; subdomain - Assign user username&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscription side-effect #2&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;Notifications&lt;/code&gt; subdomain - Send notification to slack channel&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscription side-effect #3&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;Marketing&lt;/code&gt; subdomain - Add user to mailing list&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscription side-effect #4&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;Notifications&lt;/code&gt; subdomain - Send a welcome email &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Great, so if were were to visualize the &lt;strong&gt;subdomains&lt;/strong&gt; as modules (folders) in a monolith codebase, this is what the generalization would look like:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/domain-events/intended-domain-events-1.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;Actually, we&apos;re missing something.&lt;/p&gt;
&lt;p&gt;Since we need to &lt;em&gt;assign a username&lt;/em&gt; to the user after the &lt;code class=&quot;language-text&quot;&gt;UserCreated&lt;/code&gt; event (and since that operation belongs to the &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt; subdomain), the visualization would look more like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/domain-events/intended-domain-events-2.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;Yeah. Sounds like a good plan. And let&apos;s start from scratch instead of using this &lt;a href=&quot;/wiki/anemic-domain-model/&quot;&gt;anemic&lt;/a&gt; &lt;code class=&quot;language-text&quot;&gt;UsersService&lt;/code&gt;.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Want to skip to the finished product?&lt;/b&gt; Fork the &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;repo&lt;/a&gt; for White Label, here.&lt;/p&gt;
&lt;h2 id=&quot;An-explicit-Domain-Event-interface&quot; style=&quot;position:relative;&quot;&gt;An explicit Domain Event interface&lt;a href=&quot;#An-explicit-Domain-Event-interface&quot; aria-label=&quot;An explicit Domain Event interface permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&apos;ll need an interface in order to depict what a domain event looks like. It won&apos;t need much other than the &lt;strong&gt;time&lt;/strong&gt; it was created at, and a way to get the &lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;aggregate&lt;/a&gt; id.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;IDomainEvent.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../core/types&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IDomainEvent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  dateTimeOccurred&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getAggregateId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It&apos;s more of an &lt;a href=&quot;/articles/typescript-domain-driven-design/intention-revealing-interfaces/&quot;&gt;intention revealing interface&lt;/a&gt; than anything that actually &lt;em&gt;does&lt;/em&gt; something. Half the battle in fighting confusing and complex code is using good names for things.&lt;/p&gt;
&lt;h2 id=&quot;How-to-define-Domain-Events&quot; style=&quot;position:relative;&quot;&gt;How to define Domain Events&lt;a href=&quot;#How-to-define-Domain-Events&quot; aria-label=&quot;How to define Domain Events permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A domain event is a &quot;plain ol&apos; TypeScript object&quot;. Not much to it other than it needs to implement the interface which means providing the date, the &lt;code class=&quot;language-text&quot;&gt;getAggregateId (): UniqueEntityID&lt;/code&gt; method and any other contextual information that might be useful for someone who subscribes to this domain event to know about.&lt;/p&gt;
&lt;p&gt;In this case, I&apos;m passing in the entire &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; aggregate.&lt;/p&gt;
&lt;p&gt;Some will advise against this, but for this simple example, you should be OK.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;modules/users/domain/events/UserCreated.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IDomainEvent &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../core/domain/events/IDomainEvent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../core/domain/UniqueEntityID&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; User &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../user&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserCreated&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IDomainEvent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; dateTimeOccurred&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dateTimeOccurred &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token function&quot;&gt;getAggregateId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;How-to-create-domain-events&quot; style=&quot;position:relative;&quot;&gt;How to create domain events&lt;a href=&quot;#How-to-create-domain-events&quot; aria-label=&quot;How to create domain events permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&apos;s where it gets interesting. The following class is the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; &lt;strong&gt;aggregate root&lt;/strong&gt;. Read through it. I&apos;ve commented the interesting parts.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;modules/users/domain/user.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AggregateRoot &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../core/domain/AggregateRoot&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../core/domain/UniqueEntityID&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Result &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../core/logic/Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./userId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserEmail &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./userEmail&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Guard &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../core/logic/Guard&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserCreatedEvent &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./events/userCreatedEvent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserPassword &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./userPassword&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// In order to create one of these, you need to pass&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// in all of these props. Non-primitive types are Value Objects&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// that encapsulate their own validation rules.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserEmail&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;      
  password&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserPassword&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  isEmailVerified&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  profilePicture&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  googleId&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;// Users can register w/ google&lt;/span&gt;
  facebookId&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// and facebook (instead of email + pass)&lt;/span&gt;
  username&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// User is a subclass of AggregateRoot. We&apos;ll look at the AggregateRoot&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// class again shortly.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_id&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;userId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserId &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; UserId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;caller&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserEmail &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;firstName&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lastName&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserPassword &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isEmailVerified&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isEmailVerified&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;profilePicture&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;profilePicture&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;googleId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;facebookId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;facebookId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;username&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;username&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Notice that there aren&apos;t setters for everything? &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// There are only setters for things that it makes sense&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// for there for be setters for, like `username`.&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;username&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;username &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// The constructor is private so that it forces you to use the&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// `create` Factory method. There&apos;s no way to circumvent &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// validation rules that way.&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isRegisteringWithGoogle&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;googleId &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isRegisteringWithFacebook&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;facebookId &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Here are things that cannot be null&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; guardedProps &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;firstName&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lastName&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;email&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isEmailVerified&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;isEmailVerified&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isRegisteringWithGoogle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
      &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isRegisteringWithFacebook&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// If we&apos;re not registering w/ a social provider, we also&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// need `password`.&lt;/span&gt;

      guardedProps&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;password&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Utility that checks if anything is missing&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; guardResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;againstNullOrUndefinedBulk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;guardedProps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;guardResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;succeeded&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;guardResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
    
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Create the user object and set any default values&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        username&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;username &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;username &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// If the id wasn&apos;t provided, it means that we&apos;re creating a new&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// user, so we should create a UserCreatedEvent.&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; idWasProvided &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;idWasProvided&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Method from the AggregateRoot parent class. We&apos;ll look&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// closer at this.&lt;/span&gt;
        user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDomainEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserCreated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;View this file on &lt;a href=&quot;https://github.com/stemmlerjs/white-label/blob/master/src/modules/users/domain/user.ts&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When we use the &lt;strong&gt;factory method&lt;/strong&gt; to create the &lt;strong&gt;User&lt;/strong&gt;, depending on if the User is &lt;em&gt;new&lt;/em&gt; (meaning it doesn&apos;t have an identifier yet) or it&apos;s &lt;em&gt;old&lt;/em&gt; (and we&apos;re just reconsistuting it from persistence), we&apos;ll create the &lt;code class=&quot;language-text&quot;&gt;UserCreated&lt;/code&gt; domain event.&lt;/p&gt;
&lt;p&gt;Let&apos;s look a little closer at what happens when we do &lt;code class=&quot;language-text&quot;&gt;user.addDomainEvent(new UserCreated(user));&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That&apos;s where we&apos;re creating/raising the domain event.&lt;/p&gt;
&lt;p&gt;We need to go to the &lt;code class=&quot;language-text&quot;&gt;AggregateRoot&lt;/code&gt; class to see what we do with this.&lt;/p&gt;
&lt;h2 id=&quot;Handling-createdraised-domain-events&quot; style=&quot;position:relative;&quot;&gt;Handling created/raised domain events&lt;a href=&quot;#Handling-createdraised-domain-events&quot; aria-label=&quot;Handling createdraised domain events permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you remember from our previous chats about &lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;aggregates and aggregate roots&lt;/a&gt;, the &lt;strong&gt;aggregate root&lt;/strong&gt; in DDD is the domain object that we use to perform transactions. &lt;/p&gt;
&lt;p&gt;It&apos;s the object that we refer to from the outside in order to change anything within it&apos;s &lt;a href=&quot;/wiki/invariant/&quot;&gt;invariant&lt;/a&gt; boundary.&lt;/p&gt;
&lt;p&gt;That means that anytime a transaction that wants to change the aggregate in some way (ie: a &lt;a href=&quot;/articles/oop-design-principles/command-query-segregation/&quot;&gt;command&lt;/a&gt; getting executed), it&apos;s the aggregate that is responsible for ensuring that all the business rules are satified on that object and it&apos;s not in an invalid state. &lt;/p&gt;
&lt;p&gt;It says,&lt;/p&gt;
&lt;p&gt;&quot;Yes, all good! All my invariants are satisfied, you can go ahead and save now.&quot;&lt;/p&gt;
&lt;p&gt;Or it might say,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Ah, no- you&apos;re not allowed to add more than 3 &lt;code class=&quot;language-text&quot;&gt;Genres&lt;/code&gt; to a &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; aggregate. Not OK.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Hopefully, none of that is new as we&apos;ve talked about that on the blog already.&lt;/p&gt;
&lt;p&gt;What&apos;s new is how we handle those created/raised &lt;strong&gt;domain events&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here&apos;s the aggregate root class.&lt;/p&gt;
&lt;p&gt;Check out the &lt;code class=&quot;language-text&quot;&gt;protected addDomainEvent (domainEvent: IDomainEvent): void&lt;/code&gt; method.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;core/domain/AggregateRoot.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Entity &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./Entity&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IDomainEvent &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./events/IDomainEvent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; DomainEvents &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./events/DomainEvents&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./UniqueEntityID&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Aggregate root is an `abstract` class because, well- there&apos;s &lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// no such thing as a aggregate in and of itself. It needs to _be_&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// something, like User, Vinyl, etc.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Entity&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// A list of domain events that occurred on this aggregate&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// so far.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; _domainEvents&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IDomainEvent&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_id&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;domainEvents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IDomainEvent&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_domainEvents&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addDomainEvent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;domainEvent&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IDomainEvent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Add the domain event to this aggregate&apos;s list of domain events&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_domainEvents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;domainEvent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// Add this aggregate instance to the DomainEventHandler&apos;s list of&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &apos;dirtied&apos; aggregates &lt;/span&gt;
    DomainEvents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;markAggregateForDispatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;clearEvents&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_domainEvents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;splice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_domainEvents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;logDomainEventAdded&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;domainEvent&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IDomainEvent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When we call &lt;code class=&quot;language-text&quot;&gt;addDomainEvent(domainEvent: IDomainEvent)&lt;/code&gt;, we:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;add that domain event to a list of events that &lt;em&gt;this&lt;/em&gt; aggregate has seen so far, and &lt;/li&gt;
&lt;li&gt;we tell something called &lt;code class=&quot;language-text&quot;&gt;DomainEvents&lt;/code&gt; to mark &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; for dispatch.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Almost there, let&apos;s see how the &lt;code class=&quot;language-text&quot;&gt;DomainEvents&lt;/code&gt; class &lt;em&gt;handles&lt;/em&gt; domain events.&lt;/p&gt;
&lt;h3 id=&quot;The-handler-of-domain-events-DomainEvents-class&quot; style=&quot;position:relative;&quot;&gt;The handler of domain events (DomainEvents class)&lt;a href=&quot;#The-handler-of-domain-events-DomainEvents-class&quot; aria-label=&quot;The handler of domain events DomainEvents class permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This was pretty tricky.&lt;/p&gt;
&lt;p&gt;My implementation of this is something I ported to TypeScript from &lt;a href=&quot;http://udidahan.com/2009/06/14/domain-events-salvation/&quot;&gt;Udi Dahan&apos;s 2009 blog post&lt;/a&gt; about Domain Events in C#.&lt;/p&gt;
&lt;p&gt;Here it is in it&apos;s entirety.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;core/domain/events/DomainEvents.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IDomainEvent &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./IDomainEvent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AggregateRoot &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../AggregateRoot&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../UniqueEntityID&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DomainEvents&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; handlersMap &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; markedAggregates&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AggregateRoot&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;/**
   * @method markAggregateForDispatch
   * @static
   * @desc Called by aggregate root objects that have created domain
   * events to eventually be dispatched when the infrastructure commits
   * the unit of work. 
   */&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;markAggregateForDispatch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aggregate&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AggregateRoot&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; aggregateFound &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findMarkedAggregateByID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aggregate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;aggregateFound&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;markedAggregates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aggregate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;/**
   * @method dispatchAggregateEvents
   * @static
   * @private 
   * @desc Call all of the handlers for any domain events on this aggregate.
   */&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dispatchAggregateEvents&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aggregate&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AggregateRoot&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    aggregate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;domainEvents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IDomainEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;/**
   * @method removeAggregateFromMarkedDispatchList
   * @static
   * @desc Removes an aggregate from the marked list.
   */&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;removeAggregateFromMarkedDispatchList&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aggregate&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AggregateRoot&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;markedAggregates
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findIndex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aggregate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;markedAggregates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;splice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;/**
   * @method findMarkedAggregateByID
   * @static
   * @desc Finds an aggregate within the list of marked aggregates.
   */&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findMarkedAggregateByID&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AggregateRoot&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; found&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AggregateRoot&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; aggregate &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;markedAggregates&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aggregate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        found &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; aggregate&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; found&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;/**
   * @method dispatchEventsForAggregate
   * @static
   * @desc When all we know is the ID of the aggregate, call this
   * in order to dispatch any handlers subscribed to events on the
   * aggregate.
   */&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dispatchEventsForAggregate&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; aggregate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findMarkedAggregateByID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aggregate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dispatchAggregateEvents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aggregate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      aggregate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clearEvents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeAggregateFromMarkedDispatchList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aggregate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;/**
   * @method register
   * @static
   * @desc Register a handler to a domain event.
   */&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IDomainEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    eventClassName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handlersMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;eventClassName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handlersMap&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;eventClassName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handlersMap&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;eventClassName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;callback&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;/**
   * @method clearHandlers
   * @static
   * @desc Useful for testing.
   */&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;clearHandlers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handlersMap &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;/**
   * @method clearMarkedAggregates
   * @static
   * @desc Useful for testing.
   */&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;clearMarkedAggregates&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;markedAggregates &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;/**
   * @method dispatch
   * @static
   * @desc Invokes all of the subscribers to a particular domain event.
   */&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dispatch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IDomainEvent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; eventClassName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handlersMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;eventClassName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; handlers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handlersMap&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;eventClassName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; handler &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; handlers&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;How-to-register-a-handler-to-a-Domain-Event&quot; style=&quot;position:relative;&quot;&gt;How to register a handler to a Domain Event?&lt;a href=&quot;#How-to-register-a-handler-to-a-Domain-Event&quot; aria-label=&quot;How to register a handler to a Domain Event permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To &lt;strong&gt;register&lt;/strong&gt; a handler to Domain Event, we use the static &lt;code class=&quot;language-text&quot;&gt;register&lt;/code&gt; method.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DomainEvents&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; handlersMap &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; markedAggregates&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AggregateRoot&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IDomainEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    eventClassName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handlersMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;eventClassName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handlersMap&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;eventClassName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handlersMap&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;eventClassName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;callback&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It accepts both a &lt;code class=&quot;language-text&quot;&gt;callback&lt;/code&gt; function and the &lt;code class=&quot;language-text&quot;&gt;eventClassName&lt;/code&gt;, which is the name of the class (we can get that using &lt;code class=&quot;language-text&quot;&gt;Class.name&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;When we register a handler for a domain event, it gets added to the &lt;code class=&quot;language-text&quot;&gt;handlersMap&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For 3 different domain events and 7 different handlers, the data structure for the handler&apos;s map can end up looking like this: &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;UserCreated&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Function&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Function&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Function&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;UserEdited&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Function&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Function&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;VinylCreated&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Function&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Function&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;The handlersMap is an Identity map of Domain Event names to callback functions.&lt;/p&gt;
&lt;p&gt;How &apos;bout an example of a handler?&lt;/p&gt;
&lt;h4 id=&quot;AfterUserCreated-subscriber-notifications-subdomain&quot; style=&quot;position:relative;&quot;&gt;AfterUserCreated subscriber (notifications subdomain)&lt;a href=&quot;#AfterUserCreated-subscriber-notifications-subdomain&quot; aria-label=&quot;AfterUserCreated subscriber notifications subdomain permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Remember when mentioned that we want a subscriber from within the &lt;code class=&quot;language-text&quot;&gt;Notifications&lt;/code&gt; subdomain to send us a Slack message when someone signs up?&lt;/p&gt;
&lt;p&gt;Here&apos;s an example of an &lt;code class=&quot;language-text&quot;&gt;AfterUserCreated&lt;/code&gt; subscriber setting up a handler to the &lt;code class=&quot;language-text&quot;&gt;UserCreated&lt;/code&gt; event from within the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; subdomain.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;modules/notification/subscribers/AfterUserCreated.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IHandle &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../core/domain/events/IHandle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; DomainEvents &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../core/domain/events/DomainEvents&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserCreatedEvent &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../users/domain/events/userCreatedEvent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; NotifySlackChannel &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../useCases/notifySlackChannel/NotifySlackChannel&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; User &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../users/domain/user&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AfterUserCreated&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IHandle&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserCreated&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; notifySlackChannel&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; NotifySlackChannel&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;notifySlackChannel&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; NotifySlackChannel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setupSubscriptions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;notifySlackChannel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; notifySlackChannel&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;setupSubscriptions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Register to the domain event&lt;/span&gt;
    DomainEvents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;onUserCreated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UserCreated&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;craftSlackMessage&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Hey! Guess who just joined us? =&gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;\n
      Need to reach &apos;em? Their email is &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// This is called when the domain event is dispatched.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;onUserCreatedEvent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserCreated&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; user &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;notifySlackChannel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
        channel&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;growth&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;craftSlackMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;View it on GitHub: &lt;/b&gt;Psst. It&apos;s &lt;a href=&quot;https://github.com/stemmlerjs/white-label/blob/master/src/modules/notification/subscribers/AfterUserCreated.ts&quot;&gt;here&lt;/a&gt; too. Check out the folder structure to see all the use cases.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;loose coupling&lt;/strong&gt; that happens here&apos;s is awesome. It leaves the responsibility of keeping track of &lt;em&gt;who&lt;/em&gt; needs to be alerted when a domain event is dispatched, to the &lt;code class=&quot;language-text&quot;&gt;DomainEvents&lt;/code&gt; class, and removes the need for us to couple code between &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Notifications&lt;/code&gt; directly.&lt;/p&gt;
&lt;p&gt;Not only is that good practice, it might very well be necessary! Like, when we get into designing microservices.&lt;/p&gt;
&lt;h3 id=&quot;Microservices&quot; style=&quot;position:relative;&quot;&gt;Microservices&lt;a href=&quot;#Microservices&quot; aria-label=&quot;Microservices permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When we&apos;ve split our application not only logically, but physically as well (via microservices), it&apos;s actually &lt;strong&gt;impossible&lt;/strong&gt; for us to couple two different subdomains together.&lt;/p&gt;
&lt;p&gt;We should be mindful of that when we&apos;re working on monolith codebases that we might want to someday graduate to microservives. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Be mindful of those architectural boundaries between subdomains. They should know very little about each other.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;How-does-it-work-in-a-real-life-transaction&quot; style=&quot;position:relative;&quot;&gt;How does it work in a real-life transaction?&lt;a href=&quot;#How-does-it-work-in-a-real-life-transaction&quot; aria-label=&quot;How does it work in a real life transaction permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;So we&apos;ve seen how to &lt;strong&gt;register&lt;/strong&gt; a handler from a subscriber to a domain event.&lt;/p&gt;
&lt;p&gt;And we&apos;ve seen how an &lt;strong&gt;aggregate root&lt;/strong&gt; can create, pass, and store the domain event in an array within the &lt;code class=&quot;language-text&quot;&gt;DomainEvents&lt;/code&gt; class using &lt;code class=&quot;language-text&quot;&gt;addDomainEvent(domainEvent: IDomainEvent)&lt;/code&gt; until it&apos;s ready to be dispatched.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;markedAggregates &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What are we missing?&lt;/p&gt;
&lt;p&gt;At this point, there are a few more questions I had:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How do we handle failed transactions? What if we tried to execute the &lt;code class=&quot;language-text&quot;&gt;CreateUser&lt;/code&gt; use case, but it failed before the transaction succeeded? It looks like the domain event still gets created. How do we prevent it from getting sent off to subscribers if the transaction fails? Do we need a &lt;em&gt;Unit of Work&lt;/em&gt; pattern?&lt;/li&gt;
&lt;li&gt;Who&apos;s responsibility is it to dictate when the domain event should be sent to all subscribers? Who calls &lt;code class=&quot;language-text&quot;&gt;dispatchEventsForAggregate(id: UniqueEntityId)&lt;/code&gt;?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Separating-the-creation-from-the-dispatch-of-the-domain-event&quot; style=&quot;position:relative;&quot;&gt;Separating the creation from the dispatch of the domain event&lt;a href=&quot;#Separating-the-creation-from-the-dispatch-of-the-domain-event&quot; aria-label=&quot;Separating the creation from the dispatch of the domain event permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When a domain event is &lt;u&gt;created&lt;/u&gt;, it&apos;s &lt;em&gt;not&lt;/em&gt; &lt;u&gt;dispatched&lt;/u&gt; right away.&lt;/p&gt;
&lt;p&gt;That domain event goes &lt;strong&gt;onto the aggregate&lt;/strong&gt;, then the aggregate gets marked in &lt;code class=&quot;language-text&quot;&gt;DomainEvents&lt;/code&gt; array. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;domainEvents&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// [UserCreated]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;DomainEvents&lt;/code&gt; class then waits until &lt;em&gt;something&lt;/em&gt; tells it to &lt;u&gt;dispatch&lt;/u&gt; all the handlers within the &lt;code class=&quot;language-text&quot;&gt;markedAggregates&lt;/code&gt; array that match a particular aggregate id.&lt;/p&gt;
&lt;p&gt;The question is, who&apos;s responsibility is it to say when the transaction was successful?&lt;/p&gt;
&lt;h3 id=&quot;Your-ORM-is-the-single-source-of-truth-for-a-successful-transaction&quot; style=&quot;position:relative;&quot;&gt;Your ORM is the single source of truth for a successful transaction&lt;a href=&quot;#Your-ORM-is-the-single-source-of-truth-for-a-successful-transaction&quot; aria-label=&quot;Your ORM is the single source of truth for a successful transaction permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;That&apos;s right.&lt;/p&gt;
&lt;p&gt;The thing is, a lot of these ORMs actually have mechanisms built in to execute code after things get saved to the database.&lt;/p&gt;
&lt;p&gt;For example, the &lt;a href=&quot;http://docs.sequelizejs.com/manual/hooks.html&quot;&gt;Sequelize docs&lt;/a&gt; has hooks for each of these lifecycle events.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  beforeBulkCreate&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instances, options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  beforeBulkDestroy&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  beforeBulkUpdate&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  beforeValidate&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance, options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;-&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  validate
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  afterValidate&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance, options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  - or -
  validationFailed&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance, options, error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  beforeCreate&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance, options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  beforeDestroy&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance, options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  beforeUpdate&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance, options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  beforeSave&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance, options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  beforeUpsert&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;values, options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;-&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  create
  destroy
  update
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  afterCreate&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance, options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  afterDestroy&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance, options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  afterUpdate&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance, options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  afterSave&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instance, options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  afterUpsert&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;created, options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  afterBulkCreate&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;instances, options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  afterBulkDestroy&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  afterBulkUpdate&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We&apos;re interested in the ones in (5).&lt;/p&gt;
&lt;p&gt;And &lt;a href=&quot;https://github.com/typeorm/typeorm&quot;&gt;TypeORM&lt;/a&gt; has a bunch &lt;a href=&quot;https://github.com/typeorm/typeorm/blob/master/docs/listeners-and-subscribers.md&quot;&gt;entity listeners&lt;/a&gt; which are effectively the same thing.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;@AfterLoad&lt;/li&gt;
&lt;li&gt;@BeforeInsert&lt;/li&gt;
&lt;li&gt;@&lt;strong&gt;After&lt;/strong&gt;Insert&lt;/li&gt;
&lt;li&gt;@BeforeUpdate&lt;/li&gt;
&lt;li&gt;@&lt;strong&gt;After&lt;/strong&gt;Update&lt;/li&gt;
&lt;li&gt;@BeforeRemove&lt;/li&gt;
&lt;li&gt;@&lt;strong&gt;After&lt;/strong&gt;Remove&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Again, we&apos;re mostly interested in the ones that happen &lt;em&gt;afterwards&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For example, if the &lt;code class=&quot;language-text&quot;&gt;CreateUserUseCase&lt;/code&gt; like the one shown below transaction suceeds, it&apos;s right after the &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;repository&lt;/a&gt; is able to create or update the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; that the hook gets invoked.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;modules/users/useCases/createUser/CreateUserUseCase.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UseCase &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../core/domain/UseCase&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CreateUserDTO &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./CreateUserDTO&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Either&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; left&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; right &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../core/logic/Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserEmail &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../domain/userEmail&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserPassword &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../domain/userPassword&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; User &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../domain/user&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IUserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../repos/userRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CreateUserErrors &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./CreateUserErrors&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; GenericAppError &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../core/logic/AppError&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
  GenericAppError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UnexpectedError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  CreateUserErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountAlreadyExists &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
  Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;CreateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Response&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CreateUserDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Response&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emailOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; UserEmail&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; passwordOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; UserPassword&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; combinedPropsResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;combine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; 
      emailOrError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; passwordOrError 
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;combinedPropsResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;combinedPropsResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Domain event gets created internally, here!&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
      email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; emailOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
      password&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; passwordOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
      firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
      lastName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      isEmailVerified&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;combinedPropsResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userAlreadyExists &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userAlreadyExists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountAlreadyExists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// If this transaction succeeds, we the afterCreate or afterUpdate hooks&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// get called.&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GenericAppError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UnexpectedError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Hooking-into-succesful-transactions-with-Sequelize&quot; style=&quot;position:relative;&quot;&gt;Hooking into succesful transactions with Sequelize&lt;a href=&quot;#Hooking-into-succesful-transactions-with-Sequelize&quot; aria-label=&quot;Hooking into succesful transactions with Sequelize permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Using Sequelize, we can define a callback function for each hook that takes the model name and the primary key field in order to dispatch the events for the aggregate.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;infra/sequelize/hooks/index.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; models &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../models&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; DomainEvents &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../../core/domain/events/DomainEvents&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../../core/domain/UniqueEntityID&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;dispatchEventsCallback&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; primaryKeyField&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; aggregateId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;model&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;primaryKeyField&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  DomainEvents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dispatchEventsForAggregate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aggregateId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createHooksForAggregateRoots&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; BaseUser &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  BaseUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addHook&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;afterCreate&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;m&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dispatchEventsCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;base_user_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  BaseUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addHook&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;afterDestroy&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;m&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dispatchEventsCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;base_user_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  BaseUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addHook&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;afterUpdate&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;m&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dispatchEventsCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;base_user_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  BaseUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addHook&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;afterSave&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;m&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dispatchEventsCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;base_user_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  BaseUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addHook&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;afterUpsert&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;m&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dispatchEventsCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;base_user_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Hooks not running?&lt;/b&gt;: To ensure your Sequelize hooks always run, use the &lt;i&gt;hooks: true&lt;/i&gt; option as described in &quot;&lt;a href=&quot;/blogs/sequelize/hooks/&quot;&gt;Ensuring Sequelize Hooks Always Get Run&lt;/a&gt;&quot;.&lt;/p&gt;
&lt;h3 id=&quot;Hooking-into-succesful-transactions-with-TypeORM&quot; style=&quot;position:relative;&quot;&gt;Hooking into succesful transactions with TypeORM&lt;a href=&quot;#Hooking-into-succesful-transactions-with-TypeORM&quot; aria-label=&quot;Hooking into succesful transactions with TypeORM permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Using TypeORM, here&apos;s how we can utilize the entity listener decorators to accomplish the same thing.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;@&lt;span class=&quot;token function&quot;&gt;Entity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    
  @&lt;span class=&quot;token function&quot;&gt;AfterUpdate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;dispatchAggregateEvents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; aggregateId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    DomainEvents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dispatchEventsForAggregate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aggregateId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this article, we learned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How domain logic that belongs to separate subdomains can get coupled&lt;/li&gt;
&lt;li&gt;How to create a basic domain events class&lt;/li&gt;
&lt;li&gt;How we can separate the process of notifying a subscriber to a domain event into 2 parts: creation and dispatch, and why it makes sense to do that.&lt;/li&gt;
&lt;li&gt;How to utilize the your ORM from the infrastructure layer to finalize the dispatch of handlers for your domain events&lt;/li&gt;
&lt;/ul&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Want to see the code?: &lt;/b&gt;Check it out &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now go rule out there and rule the world.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Does DDD Belong on the Frontend? - Domain-Driven Design w/ TypeScript]]></title><description><![CDATA[Frontend development is an animal of it's own. From jQuery, to Backbone, to EmberJS, to the (terribly painful) journey of dealing with…]]></description><link>https://khalilstemmler.com/articles/typescript-domain-driven-design/ddd-frontend/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/typescript-domain-driven-design/ddd-frontend/</guid><pubDate>Tue, 24 Sep 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;📣 Update: Khalil from the future here. Yes. Yes, Domain-Driven Design principles and patterns belong on the front-end. Come on now, Khalil.&lt;/b&gt; &lt;br/&gt;&lt;br/&gt;When I wrote this post back in 2019, I was primarily focused on the backend and hadn&apos;t spent enough time cutting through and making sense of the client-side space. Since then, I&apos;ve done a lot of work to identify effective ways to build sustainable front-end applications. &lt;br/&gt;&lt;br/&gt;In 2020, I wrote the &quot;&lt;a href=&quot;https://khalilstemmler.com/articles/client-side-architecture/introduction/&quot;&gt;Client Side Architecture Basics&quot;&lt;/a&gt; guide. This was my initial attempt at understanding the underlying principles at play. In short, what I&apos;ve realized is that &lt;i&gt;pretty much&lt;/i&gt; everything we&apos;re doing &lt;u&gt;architecturally&lt;/u&gt; on the backend, we could and should be doing on the frontend. &lt;br/&gt;&lt;br/&gt;For example, while it may not be popular or easy to separate concerns into &lt;a href=&quot;https://khalilstemmler.com/articles/client-side-architecture/layers/&quot;&gt;layers&lt;/a&gt;, it&apos;s essential. Why? Because with that separation comes the ability to create an efficient, scalable and testable frontend architecture. With it, if we&apos;ve figured out how to &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/how-to-test-code-coupled-to-apis-or-databases/#Core-code-and-infrastructure-code&quot;&gt;separate core code from infrastructure code&lt;/a&gt;, we can write the equivalent of &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/how-to-test-code-coupled-to-apis-or-databases/#Demonstration&quot;&gt;Acceptance (or spec) Tests&lt;/a&gt; on the frontend using extremely fast unit tests that cover a lot of ground and give you tons of confidence. &lt;br/&gt;&lt;br/&gt;Within these inner, core code layers (which are synonymous to the domain and application layers from DDD), we have the majority of what makes our app unique. There are no React components here. No mention of things like Hooks or Context. Just pure data models (value objects - domain layer concern), use cases (application layer concern), and presenters (dtos - also application layer) to name a few. &lt;br/&gt;&lt;br/&gt;Lastly, if we wish to decouple our client architecture&apos;s &lt;a href=&quot;https://khalilstemmler.com/articles/software-design-architecture/feature-driven/&quot;&gt;features&lt;/a&gt; from each other, we need to make use of the temporal nature of feature execution. We need to make our architecture event-based. This is how we end up needing &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/chain-business-logic-domain-events/&quot;&gt;Domain Events&lt;/a&gt; on the frontend. &lt;br/&gt;&lt;br/&gt;So then, does DDD belong on the front-end? Yes, because DDD is just a synthesis of what &lt;u&gt;good software design&lt;/u&gt; looks like, the technical patterns and practices we use on the backend &lt;i&gt;should&lt;/i&gt; be used on the front-end. &lt;br/&gt;&lt;br/&gt;I&apos;ve left the original post as is for now until I get a chance to update it, but if you have questions about how this could work in practice, reach out to me on &lt;a href=&quot;https://twitter.com/khalilstemmler&quot;&gt;Twitter&lt;/a&gt;.&lt;/p&gt; 
&lt;p&gt;Frontend development is an animal of it&apos;s own. From jQuery, to Backbone, to EmberJS, to the (terribly painful) journey of dealing with Webpack in it&apos;s infancy, to Angular rewrites, React hooks, and all the various module systems we&apos;ve had to pretend we knew... we&apos;ve been through a lot.&lt;/p&gt;
&lt;p&gt;I think we can all agree on the fact that modern front-end development can be complex.&lt;/p&gt;
&lt;p&gt;And it keeps getting even more complex.&lt;/p&gt;
&lt;p&gt;Readers of this blog know that I frequently write about &lt;a href=&quot;/articles/categories/domain-driven-design/&quot;&gt;Domain-Driven Design&lt;/a&gt; (an approach to software development on projects rich with business logic complexity) though I&apos;ve only exclusively explored it with respect to backend development. Despite that, I&apos;ve had several people ask me about Domain-Driven Design on the front-end.&lt;/p&gt;
&lt;p&gt;Does it make sense to use the same DDD patterns and principles on the frontend that we do on the backend?&lt;/p&gt;
&lt;p&gt;The main arguments that I&apos;ve heard for applying DDD on the frontend are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The front end space is getting just as &lt;em&gt;complex&lt;/em&gt; as the backend space. Apparently, we have &lt;em&gt;Smart UIs&lt;/em&gt; now. Modern UIs power complex HTML5 games, AR apps, VR apps, and pretty much anything else you can think about.&lt;/li&gt;
&lt;li&gt;State management can be complex. And Domain Events &lt;em&gt;look a lot like&lt;/em&gt; how we implement the &lt;strong&gt;store architecture&lt;/strong&gt; to manage application state using &lt;a href=&quot;https://redux.js.org/&quot;&gt;Redux&lt;/a&gt; or &lt;a href=&quot;https://ngrx.io/&quot;&gt;Ngrx&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So... what do you think? &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Does DDD belong in the front-end development space?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Generally speaking, &lt;u&gt;no&lt;/u&gt; (and I&apos;ll explain why in detail), although there &lt;strong&gt;are&lt;/strong&gt; some valid frontend use cases that are remniscient to how we implement DDD on the backend.&lt;/p&gt;
&lt;p&gt;Here&apos;s what we&apos;ll discuss in this article exactly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Why business logic doesn&apos;t belong in the front-end&lt;/li&gt;
&lt;li&gt;The real challenge of front-end development&lt;/li&gt;
&lt;li&gt;Parallels between DDD concepts and how they apply to the front-end&lt;/li&gt;
&lt;li&gt;Good examples of using DDD concepts in the front-end&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First argument against it I will make: DDD was meant to address business logic complexity, and business logic doesn&apos;t belong on the frontend.&lt;/p&gt;
&lt;h2 id=&quot;Business-logic-doesnt-belong-on-the-front-end&quot; style=&quot;position:relative;&quot;&gt;Business logic doesn&apos;t belong on the front-end&lt;a href=&quot;#Business-logic-doesnt-belong-on-the-front-end&quot; aria-label=&quot;Business logic doesnt belong on the front end permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Okay so &lt;strong&gt;why&lt;/strong&gt; doesn&apos;t business logic &lt;strong&gt;belong on the front-end&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;Anyone?&lt;/p&gt;
&lt;p&gt;It&apos;s because business logic is the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;high-level policy&lt;/a&gt; that &lt;em&gt;everything else&lt;/em&gt; relies on (such as the database, the web front-end, the mobile front-end, etc).&lt;/p&gt;
&lt;p&gt;And depending on your application, you might actually &lt;strong&gt;require&lt;/strong&gt; a single source of truth.&lt;/p&gt;
&lt;h3 id=&quot;Single-source-of-truth&quot; style=&quot;position:relative;&quot;&gt;Single source of truth&lt;a href=&quot;#Single-source-of-truth&quot; aria-label=&quot;Single source of truth permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Typically, in a client-server architecture, the &lt;strong&gt;backend&lt;/strong&gt; acts as the &lt;strong&gt;single source of truth&lt;/strong&gt;. The backend is the component that holds all of the high-level policy and dictates &lt;em&gt;who&lt;/em&gt; is allowed to do &lt;em&gt;what&lt;/em&gt;, &lt;em&gt;when&lt;/em&gt; they can do it, and to what &lt;em&gt;degree&lt;/em&gt; (how) they can do it.&lt;/p&gt;
&lt;p&gt;This works. And we like this because it&apos;s easy to understand the current state of the system and how everyone may use it.&lt;/p&gt;
&lt;p&gt;For someone to execute a &lt;a href=&quot;/articles/oop-design-principles/command-query-segregation/&quot;&gt;COMMAND or a QUERY&lt;/a&gt; against a resource, all they need to do is ask the &lt;strong&gt;backend&lt;/strong&gt;. This is nice because the policy that &lt;strong&gt;truly dictates&lt;/strong&gt; how that interation will go lives in one place (the backend).&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Why can&apos;t we organize the architecture differently? Why does the &lt;em&gt;backend&lt;/em&gt; need to hold the &lt;strong&gt;high-level policy&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;Well, we &lt;em&gt;can&lt;/em&gt; change up that architecture for some use cases. In fact, there are several architectures that &lt;em&gt;do&lt;/em&gt; take this approach- &lt;a href=&quot;https://en.wikipedia.org/wiki/Peer-to-peer&quot;&gt;P2P&lt;/a&gt;, for example. However, these architectures only work for &lt;strong&gt;decentralized&lt;/strong&gt; systems that &lt;strong&gt;do not&lt;/strong&gt; so desparately need a single source of truth in order to govern how the system works.&lt;/p&gt;
&lt;p&gt;To avoid going down a rabbit hole on decentralized architectures, the most common systems you&apos;ll work on are the ones where there is some sort of &lt;strong&gt;centeralized policy&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Todo App (authenticate w/ backend, store data in db)&lt;/li&gt;
&lt;li&gt;Social Networking Site (authenticate w/ backend, perform commands and queries against resources you have access to determined by the backend- &lt;em&gt;this&lt;/em&gt; is domain complexity)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even some P2P apps need centralization:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Even in a &lt;em&gt;paid&lt;/em&gt; decentralized messaging system, the client needs to check the &lt;strong&gt;centeralized&lt;/strong&gt; server to see if the acccount has sufficient credits.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;To-protect-against-change&quot; style=&quot;position:relative;&quot;&gt;To protect against change&lt;a href=&quot;#To-protect-against-change&quot; aria-label=&quot;To protect against change permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Frontends are a lot more suceptible to change than backends.&lt;/p&gt;
&lt;p&gt;Architecturally, the front-end is a &lt;strong&gt;low-level detail&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That means it&apos;s more likely that we&apos;ll scrap the entire front end for a new one (as my previous company had actually done several times, moving from Backbone to AngularJS to Angular), than scrap the entire backend for a new one.&lt;/p&gt;
&lt;p&gt;The factors at play here are &lt;strong&gt;stability&lt;/strong&gt; and &lt;strong&gt;volatility&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Stability&quot; style=&quot;position:relative;&quot;&gt;Stability&lt;a href=&quot;#Stability&quot; aria-label=&quot;Stability permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In Uncle Bob&apos;s &lt;em&gt;Clean Architecture&lt;/em&gt;, he wrote about the &lt;a href=&quot;/wiki/stable-dependency-principle/&quot;&gt;Stable Dependency Principle&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;He said that,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Components&apos; dependencies should be in the direction of stability&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To visualize that, if we were to look at the &lt;a href=&quot;&quot;&gt;clean architecture&lt;/a&gt; that he talks about, we&apos;d notice that it&apos;s the &lt;strong&gt;domain layer&lt;/strong&gt; that holds the highest level of &lt;strong&gt;stability&lt;/strong&gt; AND &lt;strong&gt;policy&lt;/strong&gt;.&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; style=&quot;width: 50%;&quot; src=&quot;/img/wiki/package-principles/stability.svg&quot;&gt;
&lt;p class=&quot;caption&quot;&gt;Clean architecture showing that stability goes towards the domain layer&lt;/p&gt;
&lt;p&gt;Why is that? Why does the &lt;strong&gt;domain layer&lt;/strong&gt; hold the highest level of policy and stability?&lt;/p&gt;
&lt;p&gt;That&apos;s because the &lt;strong&gt;domain layer&lt;/strong&gt; contains the domain modeling code that most closely describes how your business &lt;em&gt;actually works&lt;/em&gt; in the real world. &lt;/p&gt;
&lt;p&gt;Since it&apos;s very unlikely that your business will drastically change, that means that the code that best describes your business is &lt;em&gt;also unlikely&lt;/em&gt; to need change.&lt;/p&gt;
&lt;p&gt;That&apos;s what makes the &lt;strong&gt;domain layer&lt;/strong&gt; quite stable.&lt;/p&gt;
&lt;p&gt;And &lt;a href=&quot;/wiki/stable-dependency-principle/&quot;&gt;stable components&lt;/a&gt; are components that we can rely on. Therefore, it makes sense to organize the unstable (volatile) components to depend on the stable ones, but never make a stable component rely on something unstable. Like a back-end relying on a front-end. &lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;An examplary blunder:&lt;/b&gt; &lt;a href=&quot;https://softwareontheroad.com/reversing-tinder-api-with-nodejs/?utm_source=reddit-webdev&amp;utm_medium=group_post&quot;&gt;Here&apos;s one&lt;/a&gt;. It&apos;s titled, &quot;Exploiting Tinder to get paid features for free&quot;. The &quot;TL;DR? Too much on client side&quot; - via &lt;a href=&quot;https://www.reddit.com/r/javascript/comments/d8rbcv/exploiting_tinder_to_get_paid_features_for_free/f1ch6b7/&quot;&gt;Reddit&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Opinion&lt;/b&gt;: I think the reason why new developers usually end up working in front-end development jobs straight out of school is because technical managers are aware that the front-end is volatile, and if it were mucked up by a new hire, the business would still be OK. There&apos;s a lot more at risk for backend development because it&apos;s so critical.&lt;/p&gt;
&lt;p&gt;Look at how we normally organize the components of a generic web app.&lt;/p&gt;
&lt;img style=&quot;width: 100%;&quot; src=&quot;/img/blog/ddd-frontend/generic-application-architecture.svg&quot;/&gt;
&lt;p&gt;Notice that the &lt;strong&gt;application layer&lt;/strong&gt; and the &lt;strong&gt;domain layer&lt;/strong&gt; are in the middle of this architecture?&lt;/p&gt;
&lt;p&gt;And if we looked at it as a graph, it would form a &lt;a href=&quot;https://en.wikipedia.org/wiki/Directed_acyclic_graph&quot;&gt;Directed Acyclic Graph - DAG&lt;/a&gt; where the high-level components are on the top, and the low-level  ones are on the bottom.&lt;/p&gt;
&lt;img style=&quot;width: 100%;&quot; src=&quot;/img/blog/ddd-frontend/component-volatility.svg&quot;/&gt;
&lt;h4 id=&quot;The-Open-Closed-Principle&quot; style=&quot;position:relative;&quot;&gt;The Open-Closed Principle&lt;a href=&quot;#The-Open-Closed-Principle&quot; aria-label=&quot;The Open Closed Principle permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;In fact, when we do this, we&apos;re satisfying the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;Open-Closed Principle&lt;/a&gt; &lt;em&gt;architecturally&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;OCP says that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Components should be open for extension, but closed for modification &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If your boss told you to change the color of the background on the client app, is that going to break the backend?&lt;/p&gt;
&lt;p&gt;No, because architecturally, our system is open for extension (via the front-end, we can change the UI we build on top of it) but closed for modification. &lt;/p&gt;
&lt;p&gt;This is what we&apos;re doing when we &lt;strong&gt;put all the high-level policy in the backend&lt;/strong&gt; and ensure that the front-end contains no high-level policy.&lt;/p&gt;
&lt;p&gt;I think I&apos;ve said enough on that for now. That&apos;s why the front-end shouldn&apos;t have business logic.&lt;/p&gt;
&lt;h3 id=&quot;div-classexpandable-sectionCategories-of-business-logic-sorted-by-policydiv-classexpandable-section-button-onclicktoggleExpandableSectionlogic-typesdivdiv&quot; style=&quot;position:relative;&quot;&gt;&lt;div class=&quot;expandable-section&quot;&gt;Categories of business logic sorted by policy&lt;div class=&quot;expandable-section-button&quot; onclick=&quot;toggleExpandableSection(&apos;logic-types&apos;)&quot;&gt;+&lt;/div&gt;&lt;/div&gt;&lt;a href=&quot;#div-classexpandable-sectionCategories-of-business-logic-sorted-by-policydiv-classexpandable-section-button-onclicktoggleExpandableSectionlogic-typesdivdiv&quot; aria-label=&quot;div classexpandable sectionCategories of business logic sorted by policydiv classexpandable section button onclicktoggleExpandableSectionlogic typesdivdiv permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div id=&quot;logic-types&quot; class=&quot;expandable-section-content&quot;&gt;
  &lt;p&gt;These are the categories of business logic ordered from lowest  level policy to highest level policy.&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;6. Presentation logic: Logic that&apos;s concerned with how we present something to the user.&lt;/li&gt;
    &lt;li&gt;5. Data access / adapter logic: Logic concerned with access an infrastructure laywer concern like caches, databases, front-ends, etc.&lt;/li&gt;
    &lt;li&gt;4. Application layer logic / use case: Application specific logic. In an enterprise with several different applications (think Google&apos;s Docs, Sheets, Maps, etc), each application has it&apos;s own set of use cases and policy that governs those use cases.&lt;/li&gt;
    &lt;li&gt;3. Domain layer logic: Core business that doesn&apos;t quite fit within the confines of a single entity.&lt;/li&gt;
    &lt;li&gt;2. Validation logic: Logic that ensures that objects are valid.&lt;/li&gt;
    &lt;li&gt;1. Core business logic: Logic that can be confined to a single entity. Ex: in a blog, the fact that a `comment` entity is created with `approved: true` or `approved: false` should be central the creation of a `comment` domain object.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;h3 id=&quot;div-classexpandable-sectionExamples-of-change-rippling-into-other-componentsdiv-classexpandable-section-button-onclicktoggleExpandableSectionrippledivdiv&quot; style=&quot;position:relative;&quot;&gt;&lt;div class=&quot;expandable-section&quot;&gt;Examples of change rippling into other components&lt;div class=&quot;expandable-section-button&quot; onclick=&quot;toggleExpandableSection(&apos;ripple&apos;)&quot;&gt;+&lt;/div&gt;&lt;/div&gt;&lt;a href=&quot;#div-classexpandable-sectionExamples-of-change-rippling-into-other-componentsdiv-classexpandable-section-button-onclicktoggleExpandableSectionrippledivdiv&quot; aria-label=&quot;div classexpandable sectionExamples of change rippling into other componentsdiv classexpandable section button onclicktoggleExpandableSectionrippledivdiv permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div id=&quot;ripple&quot; class=&quot;expandable-section-content&quot;&gt;
  &lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Pricing model change&lt;/b&gt;: Assume we have some Software as a Service application and we want to change the pricing model. If we change the pricing model, we&apos;re changing an essential piece of domain layer logic. That has potential to affect &lt;i&gt;everything else&lt;/i&gt; like the &lt;b&gt;ui&lt;/b&gt; (in order to show new options and perhaps restrict pages) and the &lt;b&gt;database&lt;/b&gt; (if new tiers were added, we might need to persist those somehow).&lt;/p&gt;
  &lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Max users in an account&lt;/b&gt;: Let&apos;s say there exists an application with &lt;b&gt;Users&lt;/b&gt; and &lt;b&gt;Accounts&lt;/b&gt;. An account has several users. Assume that this was un-capped for a long time. Accounts could have as many users as they wanted. Suddenly, we decide to add a business rule only allowing &lt;b&gt;3 users to an account&lt;/b&gt;. What&apos;s affected? &lt;i&gt;Think about it and share in the comments&lt;/i&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;The-real-challenge-of-front-end-development-is-architecture&quot; style=&quot;position:relative;&quot;&gt;The real challenge of front-end development is architecture&lt;a href=&quot;#The-real-challenge-of-front-end-development-is-architecture&quot; aria-label=&quot;The real challenge of front end development is architecture permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If we&apos;re on the same page about keeping domain logic divorced from the front-end, let&apos;s direct our attention to the REAL complexity we&apos;re facing when building user interfaces.&lt;/p&gt;
&lt;p&gt;Temporarily ignoring complex things like rendering svgs, projecting 3D shapes, or facial detection, the most common complexity faced in &lt;strong&gt;large front-end applications&lt;/strong&gt; is the architecture. &lt;/p&gt;
&lt;p&gt;Specifically, it&apos;s the front-end stack that we use.&lt;/p&gt;
&lt;p&gt;The goal of every front-end framework is to simplify the way that we:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Define data (data storage)&lt;/li&gt;
&lt;li&gt;Signal that data changes (change detection)&lt;/li&gt;
&lt;li&gt;React to data changes (data flow)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There&apos;s no shortage of approaches to handle this. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Data storage: Redux/Ngrx store architecture, service-oriented architecture, etc&lt;/li&gt;
&lt;li&gt;Change detection: Angular Zones, Vue&apos;s `Object.defineProperty(), React reconcilliation, etc&lt;/li&gt;
&lt;li&gt;React to data changes: Observables, hooks, one-way data flow, etc&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These early architectural decisions have a &lt;strong&gt;profound impact&lt;/strong&gt; on the quality and ease of development for the remainder of the project&apos;s lifespan. &lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&amp;quot;In my opinion, the most challenging part of front-end development is choosing the stack and ensuring that everyone writes code that adheres to the architectural contours of the decided stack.&amp;quot; - &lt;a href=&quot;https://t.co/dHWnW3dsu3&quot;&gt;https://t.co/dHWnW3dsu3&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/react?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#react&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/angular?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#angular&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/VueJS?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#VueJS&lt;/a&gt;&lt;/p&gt;&amp;mdash; Khalil Stemmler🔥 (@khalilstemmler) &lt;a href=&quot;https://twitter.com/khalilstemmler/status/1176606328875298820?ref_src=twsrc%5Etfw&quot;&gt;September 24, 2019&lt;/a&gt;&lt;/blockquote&gt; &lt;script async src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;br/&gt;
&lt;p&gt;I think it would be correct to say that &lt;em&gt;this&lt;/em&gt; is as far as &lt;strong&gt;high-level policy&lt;/strong&gt; goes on the front-end. The stack we choose. And the code we write within the framework of choice are the &lt;strong&gt;low-level&lt;/strong&gt; details.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When you choose a frontend architecture, that high-level decision influences &lt;em&gt;the way&lt;/em&gt; you write (low-level) code for the rest of the project.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Choosing that stack, organizing code, and &lt;u&gt;consistently ensuring that code is getting written&lt;/u&gt; within the &lt;strong&gt;architectural choices&lt;/strong&gt; is (arguably) the most challenging part of front-end development (some might say it&apos;s actually CSS 🙂).&lt;/p&gt;
&lt;p&gt;&lt;u&gt;None of this has to do with encapsulating a domain model to simplify business logic complexity&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;And again, that&apos;s what DDD is primarily meant to do.&lt;/p&gt;
&lt;h2 id=&quot;Drawing-parallels-to-DDD&quot; style=&quot;position:relative;&quot;&gt;Drawing parallels to DDD&lt;a href=&quot;#Drawing-parallels-to-DDD&quot; aria-label=&quot;Drawing parallels to DDD permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&apos;s &lt;em&gt;try&lt;/em&gt; to look at the front-end through DDD lenses.&lt;/p&gt;
&lt;p&gt;The first thing we try to do in DDD is understand the &lt;em&gt;domain&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Let&apos;s use &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;White Label&lt;/a&gt;, the vinyl-trading application, for example. &lt;/p&gt;
&lt;h3 id=&quot;The-subdomain-of-the-front-end&quot; style=&quot;position:relative;&quot;&gt;The subdomain of the front-end&lt;a href=&quot;#The-subdomain-of-the-front-end&quot; aria-label=&quot;The subdomain of the front end permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;White Label&lt;/strong&gt; is an app where traders can sign up, list the vinyl that they own within their collection, make trades and accept offers.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-aggregates/WhiteLabelAddVinyl6.svg&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Add new vinyl - Fill in album details.&lt;/p&gt;
&lt;p&gt;For an application like this, you can only assume that there&apos;s going to be a LOT of business logic complexity.&lt;/p&gt;
&lt;p&gt;Setting up trades, accepting offers, updating offers, handling inventory, not to mention shipping and tracking. There&apos;s a lot going on.&lt;/p&gt;
&lt;p&gt;Subdomains that probably exist are &lt;code class=&quot;language-text&quot;&gt;Trading&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Shipping&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Billing&lt;/code&gt;, and more.&lt;/p&gt;
&lt;p&gt;Though, none of that concerns the front-end.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-intro/ddd-diagram.svg&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Choices that we make on the front-end should be mutually exclusive from our domain model.&lt;/p&gt; 
&lt;p&gt;The majority of our front-end code is &lt;em&gt;dumb&lt;/em&gt; to the actual problem domain. It largely entails simply &lt;strong&gt;validating forms&lt;/strong&gt; before making API calls, &lt;strong&gt;presenting data&lt;/strong&gt;, and responding to events like &lt;em&gt;clicks&lt;/em&gt; or &lt;em&gt;button presses&lt;/em&gt;.&lt;/p&gt;
&lt;img class=&quot;centered-image&quot; style=&quot;width: 75%;&quot; src=&quot;/img/blog/ddd-frontend/frontend-subdomain.svg&quot;/&gt;
&lt;p class=&quot;caption&quot;&gt;The primary concepts of coding within the DOM.&lt;/p&gt; 
&lt;p&gt;While that&apos;s the &lt;strong&gt;common&lt;/strong&gt; way to look at how we interact with front-end concerns on a daily basis, it&apos;s not always like that.&lt;/p&gt;
&lt;p&gt;Sometimes, in presentation-heavy applications like games or applications with canvas / D3 rendering, domain logic &lt;em&gt;does&lt;/em&gt; get &lt;u&gt;duplicated into the presentation layer in order to influence how things are presented&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;I&apos;ll dive deeper into that in &lt;strong&gt;&quot;Good examples of using DDD concepts in the front-end&quot;&lt;/strong&gt;, so keep reading.&lt;/p&gt;
&lt;h3 id=&quot;Screaming-architecture--package-by-module-and-subdomain&quot; style=&quot;position:relative;&quot;&gt;Screaming architecture / package by module and subdomain&lt;a href=&quot;#Screaming-architecture--package-by-module-and-subdomain&quot; aria-label=&quot;Screaming architecture  package by module and subdomain permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;With respect to the way that I organize code on the front-end, I&apos;ll still implement what&apos;s called &lt;strong&gt;packaging by module&lt;/strong&gt;, which means that we organize code based on the subdomains.&lt;/p&gt;
&lt;p&gt;If these are the level subdomains: &lt;code class=&quot;language-text&quot;&gt;Trading&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Shipping&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Billing&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then, in a React-Redux project, my folder structure for the &lt;code class=&quot;language-text&quot;&gt;Trading&lt;/code&gt; subdomain might look like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;src
  modules 
    ...
    trading             # Trading module
      components/         # All components for trading subdomain
      models/             # All models in trading subdomain
      pages/              # All pages in trading subdomain
      redux/              # All the redux for the trading subdomain
      services/           # All services that interact with trading API
      styles/             # All styles for trading components
      index.ts
  ...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Value-Objects-and-validation-logic&quot; style=&quot;position:relative;&quot;&gt;Value Objects and validation logic&lt;a href=&quot;#Value-Objects-and-validation-logic&quot; aria-label=&quot;Value Objects and validation logic permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In Domain-Driven Design, &lt;strong&gt;value objects&lt;/strong&gt; are responsible for validation logic.&lt;/p&gt;
&lt;p&gt;If we had a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; class and we wanted to ensure that no &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; could ever be created with an invalid &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt;, we&apos;d change the type of &lt;code class=&quot;language-text&quot;&gt;email:string&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;email: UserEmail&lt;/code&gt; and create a &lt;code class=&quot;language-text&quot;&gt;UserEmail&lt;/code&gt; value object to control creation of the valid &lt;code class=&quot;language-text&quot;&gt;UserEmail&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;See the example of a &lt;code class=&quot;language-text&quot;&gt;UserEmail&lt;/code&gt; class below.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; TextUtil &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Guard &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../core&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserEmailProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserEmail&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ValueObject&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserEmailProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Private constructor. No one can say &quot;new UserEmail(&apos;diddle&apos;)&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserEmailProps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Factory method, can do UserEmail.create() &lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserEmailProps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserEmail&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;againstNullOrUndefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; 
      &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;TextUtil&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValidEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserEmail&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Email not provided or not valid.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserEmail&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Sharing-code-between-the-front-end-and-the-back-end&quot; style=&quot;position:relative;&quot;&gt;Sharing code between the front-end and the back-end&lt;a href=&quot;#Sharing-code-between-the-front-end-and-the-back-end&quot; aria-label=&quot;Sharing code between the front end and the back end permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;That begs the question, since &lt;strong&gt;validation logic&lt;/strong&gt; is one of the forms of logic &lt;em&gt;does&lt;/em&gt; have a place on the front-end, should we &lt;strong&gt;package this value object class&lt;/strong&gt; and &lt;em&gt;share&lt;/em&gt; it on both the front-end and back-end?&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Shared kernel&lt;/b&gt;: In DDD lingo, a shared kernel is a library or package of domain objects shared across the entire enterprise. This could be an &lt;b&gt;npm&lt;/b&gt; library.&lt;/p&gt;
&lt;p&gt;You could do that, but sharing &lt;strong&gt;domain-layer code&lt;/strong&gt; between the front-end and the back-end is an &lt;strong&gt;architecturally messy decision&lt;/strong&gt; that violates the &lt;a href=&quot;/wiki/stable-dependency-principle/&quot;&gt;Stable Dependency Principle (SDP)&lt;/a&gt; and the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;Single Responsibility Principle&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A component should have one reason to change. And if that component is  relied on by both the frontend and the backend, that means it has two  reasons to change.&lt;/p&gt;
&lt;p&gt;If a change for a low-level component like the frontend can ripple into something that breaks a high-level component like the backend, then we&apos;re also violating &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;OCP&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;If you want to go this route, I&apos;d advise having a client-side library that&apos;s completely separate from your backend models.&lt;/p&gt;
&lt;h3 id=&quot;DTOs-are-your-client-side-models&quot; style=&quot;position:relative;&quot;&gt;DTOs are your client side models&lt;a href=&quot;#DTOs-are-your-client-side-models&quot; aria-label=&quot;DTOs are your client side models permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You probably already knew this, but your &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;dtos&lt;/a&gt; that you pass from the backend are pretty much your client-side models.&lt;/p&gt;
&lt;p&gt;If your DTOs are just TypeScript interfaces, you can copy those to the  front-end or distribute them within your client-side library.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;user/services/userService.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IUserService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getUserByUserId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserService&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseAPI&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IUserService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 
  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getUserByUserId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Retrieve the user from the API&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;user/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;userId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Type the response&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;Client-side user service&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Client-side classes or interfaces?&lt;/b&gt;: Depending on if you need to add behavioural capabilities to a client-side model, you may need to also request additional metadata in  order to &lt;b&gt;hydrate&lt;/b&gt; the dto into a client-side &lt;i&gt;class&lt;/i&gt; with instance methods instead of just deserialized json object. See the &lt;b&gt;Call Flow&lt;/b&gt; example in the final section.&lt;/p&gt;
&lt;h3 id=&quot;Domain-Events-are-served-via-websockets-or-push-notifications&quot; style=&quot;position:relative;&quot;&gt;Domain Events are served via websockets or push notifications&lt;a href=&quot;#Domain-Events-are-served-via-websockets-or-push-notifications&quot; aria-label=&quot;Domain Events are served via websockets or push notifications permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;/blogs/domain-driven-design/where-do-domain-events-get-dispatched/&quot;&gt;Domain events&lt;/a&gt; get created and emitted when something interesting happens from within one subdomain.&lt;/p&gt;
&lt;p&gt;Other subdomains can subscribe to interesting domain events in order to chain complex domain logic.&lt;/p&gt;
&lt;p&gt;In the front-end space, this makes a lot of sense to implement with websockets.&lt;/p&gt;
&lt;p&gt;If a front-end app sat there listening in on a websocket connection to the backend with a &lt;code class=&quot;language-text&quot;&gt;switch&lt;/code&gt; statement hooked up to the client side, the client could present interesting things to the user in the UI as they happen.&lt;/p&gt;
&lt;p&gt;But the client-side is &lt;strong&gt;never responsible for directly creating domain events&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That&apos;s something I&apos;ve seen recently; where developers confuse a &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt; from &lt;a href=&quot;/articles/oop-design-principles/command-query-segregation/&quot;&gt;CQRS&lt;/a&gt; with a Domain Event.&lt;/p&gt;
&lt;h2 id=&quot;Good-examples-of-using-DDD-concepts-in-the-front-end&quot; style=&quot;position:relative;&quot;&gt;Good examples of using DDD concepts in the front-end&lt;a href=&quot;#Good-examples-of-using-DDD-concepts-in-the-front-end&quot; aria-label=&quot;Good examples of using DDD concepts in the front end permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are some really good use cases where it makes sense to lean on some of the DDD concepts, in a front-end context.&lt;/p&gt;
&lt;p&gt;Here are a few tactics that I&apos;ve applied in a previous role.&lt;/p&gt;
&lt;h3 id=&quot;Hydrating-domain-models&quot; style=&quot;position:relative;&quot;&gt;Hydrating domain models&lt;a href=&quot;#Hydrating-domain-models&quot; aria-label=&quot;Hydrating domain models permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;1st person shooter&lt;/b&gt;: Consider you&apos;ve built an online game like Counter Strike: GO, and you want to be able to release new gun skins, gun models, gun sounds, and what not. Your goal is to be able to dynamically create new guns with their color, render, and behavior (recoil, burst rate) without having to deploy a patch everytime a new gun comes out. Or perhaps &lt;b&gt;players&lt;/b&gt; themselves could create their own frankenstein-y guns. &lt;br/&gt; &lt;br/&gt; Since the front-end is responsible for the presentation of those guns, a dto could return not only the basic details about the gun, but also all of the additional metadata required in order to hydrate an instance of a gun class, so that the instance methods and properties dynamically reflect it&apos;s presentation and behaviour within the game.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Call flow visualizations&lt;/b&gt;: Earlier this year I worked on &lt;b&gt;Talkify&lt;/b&gt;, a visual call flow tool built with Angular and D3, enabling small business owners to drag and drop &lt;i&gt;Call Flow Nodes&lt;/i&gt; onto a canvas in order to create these really complex call flows. Each Call Flow Node was different in the sense that they all had their own &lt;i&gt;presentation&lt;/i&gt;, &lt;i&gt;behavior&lt;/i&gt;, &lt;i&gt;chaining rules&lt;/i&gt; (am I allowed to put something after this, or is this a terminal node), and &lt;i&gt;editable form&lt;/i&gt;. &lt;br/&gt;&lt;br/&gt;For example, the &lt;b&gt;number node&lt;/b&gt; acted differently from the &lt;b&gt;busines hours node&lt;/b&gt; and the &lt;b&gt;AWS lambda node&lt;/b&gt; (yeah, it was really cool- you could hook up lambda functions to a call flow).  &lt;br/&gt;&lt;br/&gt;Again, there was a sort of dynamicism required because the backend team would deploy new Call Flow Nodes all the time, and the front-end needed only require the metadata for each node via API call in order determine how to render it and how to hook up the specific &lt;b&gt;presentation logic&lt;/b&gt; for each node.&lt;/p&gt;
&lt;h3 id=&quot;Real-time-domain-events&quot; style=&quot;position:relative;&quot;&gt;Real-time domain events&lt;a href=&quot;#Real-time-domain-events&quot; aria-label=&quot;Real time domain events permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Location tracking&lt;/b&gt;: Also earlier this year, I was doing work on a mobile app for a company that builds marine magnetometers. Using a steady stream of domain events from a backend application, the mobile app would render a map of your location, your boat&apos;s position on the map, and the direction of the magnetometer at the back of the boat.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Git and CI Tools&lt;/b&gt;: Tools like GitHub, Gitlab, and Netlify do this all the time. When someone merges a PR, or a build fails, there&apos;s usually a UI change that happens if you&apos;re looking at the same page.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;Takeaway&quot; style=&quot;position:relative;&quot;&gt;Takeaway&lt;a href=&quot;#Takeaway&quot; aria-label=&quot;Takeaway permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Business logic doesn&apos;t belong on the front-end because of single-source of truth constraints in centralized applications, the front-end is volatile and prone to change, and components should always point towards the direction of stability.&lt;/li&gt;
&lt;li&gt;The real complexity of front-end development is maintaining a consistent architecture based on the decisions of the tech stack, not encapsulating a domain model.&lt;/li&gt;
&lt;li&gt;Be careful to not violate OCP when sharing code between the front-end and the back-end. Create a client-side library.&lt;/li&gt;
&lt;li&gt;Applications with heavy amounts of presentation logic are the ones that would most benefit from using a client-side presentation model from hydrated domain objects (DTOs).&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Organizing App Logic with the Clean Architecture [with Examples]]]></title><description><![CDATA[How many times have you been working on an application, and in the middle of writing some logic, asked yourself: "Is this the right place to…]]></description><link>https://khalilstemmler.com/articles/software-design-architecture/organizing-app-logic/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/software-design-architecture/organizing-app-logic/</guid><pubDate>Mon, 16 Sep 2019 15:04:10 GMT</pubDate><content:encoded>&lt;div class=&quot;solid-book-cta course-cta&quot;&gt;
  &lt;div class=&quot;solid-book-logo-container&quot;&gt;
    &lt;img src=&quot;/img/resources/solid-book/book-logo.png&quot;/&gt;
  &lt;/div&gt;
  &lt;p&gt;This topic is taken from Solid Book - The Software Architecture &amp; Design Handbook w/ TypeScript + Node.js. &lt;a href=&quot;https://solidbook.io&quot;&gt;Check it out&lt;/a&gt; if you like this post.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;How many times have you been working on an application, and in the middle of writing some logic, asked yourself:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Is this the right place to put this logic?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There&apos;s a lot that goes into figuring out where something belongs. &lt;/p&gt;
&lt;p&gt;First, you have to understand the domain that you&apos;re working in. That&apos;s how you figure out the &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;subdomains&lt;/a&gt; in your app.&lt;/p&gt;
&lt;p&gt;Then, for each subdomain, you have to identify all the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt; and which &lt;strong&gt;actors&lt;/strong&gt; are allowed to execute them.&lt;/p&gt;
&lt;p&gt;This is &lt;a href=&quot;/wiki/conways-law/&quot;&gt;Conway&apos;s Law&lt;/a&gt; &lt;strong&gt;in action&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;What I&apos;ve found to be &lt;u&gt;the most challenging part&lt;/u&gt;, especially for developers new to &lt;a href=&quot;/articles/categories/enterprise-node-type-script/&quot;&gt;enterprise application development&lt;/a&gt; that have &lt;a href=&quot;/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;moved well-past simple CRUD MVC apps&lt;/a&gt;, is implementing a &lt;strong&gt;layered architecture&lt;/strong&gt; to separate the concerns of app development.&lt;/p&gt;
&lt;p&gt;The challenge seems to be understanding &lt;em&gt;which layer&lt;/em&gt; exactly to place logic.&lt;/p&gt;
&lt;!-- If you know what the **layers** are, and you know what each layer _is for_, then you **never have to be confused** about where logic should go, ever again. --&gt;
&lt;p&gt;In this article, we&apos;ll learn about the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Clean Architecture, and why we should separate the concerns of large applications into layers.&lt;/li&gt;
&lt;li&gt;The 6 most common types of application logic and which layer they belong to.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;The-Clean-Architecture--Layered-Architecture&quot; style=&quot;position:relative;&quot;&gt;The Clean Architecture / Layered Architecture&lt;a href=&quot;#The-Clean-Architecture--Layered-Architecture&quot; aria-label=&quot;The Clean Architecture  Layered Architecture permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Robert Martin wrote about &lt;em&gt;Clean Architecture&lt;/em&gt; in his book of the same name. Although a bit of a challenging read (took me 2 really good reads), it&apos;s amazing. It teaches you about how to organize and group code into components, and then how to organize an application that connects those components to things like databases, APIs, web servers and other external things that we need to power applications.&lt;/p&gt;
&lt;p&gt;A really simplified version of what the clean architecture might look like:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/clean-architecture/group.svg&quot; alt=&quot;Simplified Clean Architecture&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Domain-Layer&quot; style=&quot;position:relative;&quot;&gt;Domain Layer&lt;a href=&quot;#Domain-Layer&quot; aria-label=&quot;Domain Layer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In one layer (domain) we have all of the important stuff: the entities, business logic, rules and events. This is the irreplaceable stuff in our software that we can&apos;t just swap out for another library or framework. It&apos;s also the stuff that&apos;s much less likely to need to change because it represents &lt;em&gt;what our business does&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;For example, if we&apos;re an app that sells books, we sell books. If we&apos;re an app that finds parking spots, the domain layer contains the &lt;em&gt;core logic&lt;/em&gt; to find parking spots. &lt;/p&gt;
&lt;p&gt;Because we&apos;re unlikely to change the core essense of what our business does, the domain layer is the most &lt;a href=&quot;/wiki/stable-dependency-principle/&quot;&gt;stable layer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The domain layer assumes a kind of &lt;strong&gt;higher-level policy&lt;/strong&gt; that everything else relies on. &lt;/p&gt;
&lt;h3 id=&quot;Infra-everything-else-layer&quot; style=&quot;position:relative;&quot;&gt;Infra (everything-else) layer&lt;a href=&quot;#Infra-everything-else-layer&quot; aria-label=&quot;Infra everything else layer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The other layer (infra) contains everything that actually spins up the code in the domain layer to execute.&lt;/p&gt;
&lt;h2 id=&quot;Clean-architecture-expanded&quot; style=&quot;position:relative;&quot;&gt;Clean architecture expanded&lt;a href=&quot;#Clean-architecture-expanded&quot; aria-label=&quot;Clean architecture expanded permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We can &lt;strong&gt;generally&lt;/strong&gt; express the clean architecture as &lt;em&gt;domain&lt;/em&gt; and &lt;em&gt;infrastructure&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Stuff that&apos;s specific to our business is &lt;strong&gt;domain&lt;/strong&gt;, and the adapter-stuff that just hooks into the technologies that enable us to run a web app (database, web servers, controllers, caches, etc) is the &lt;strong&gt;infrastructure&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;But the devil is in the details.&lt;/p&gt;
&lt;p&gt;If we wipe our glasses off, a more detailed view of the clean architecture would look like this.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/software-architecture-design/app-logic-layers.svg&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;For &lt;a href=&quot;/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;trivially small applications&lt;/a&gt;, this might seem like overkill. But for applications that are expected to live a long life, be maintained by larger teams, and make / save a company money, it&apos;s vital to figure out how to separate the concerns and where to put logic.&lt;/p&gt;
&lt;p&gt;Failure to address that complexity and solve it with a better architecture can turn a project &lt;em&gt;legacy-mode&lt;/em&gt;, real quick.&lt;/p&gt;
&lt;p&gt;Without further ado, here are the 6 most common types of application logic that find their way into large applications.&lt;/p&gt;
&lt;h2 id=&quot;1-Presentation-Logic&quot; style=&quot;position:relative;&quot;&gt;1. Presentation Logic&lt;a href=&quot;#1-Presentation-Logic&quot; aria-label=&quot;1 Presentation Logic permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Logic that&apos;s concerned with how we present something to the user.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Most apps used by consumers have front-ends. This type of logic is entirely concerned with &lt;em&gt;how we present something to the user&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;It&apos;s the HTML, CSS and JavaScript that we write that turns a blank page into a well-designed, living, breathing front-end application.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sass&quot;&gt;&lt;pre class=&quot;language-sass&quot;&gt;&lt;code class=&quot;language-sass&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.container&lt;/span&gt;
&lt;span class=&quot;token property-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white;&lt;/span&gt;
&lt;span class=&quot;token property-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; blue;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Dumb-UIs-should-contain-no-business-rules&quot; style=&quot;position:relative;&quot;&gt;Dumb UIs should contain no business rules&lt;a href=&quot;#Dumb-UIs-should-contain-no-business-rules&quot; aria-label=&quot;Dumb UIs should contain no business rules permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There&apos;s a principle called &lt;strong&gt;Dumb UI&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The idea is to keep the UI logic divorced from any &lt;strong&gt;domain-layer&lt;/strong&gt; logic, because the domain-layer logic acts as dependency to &lt;em&gt;everything else&lt;/em&gt; in the architecture.&lt;/p&gt;
&lt;p&gt;The front-end is &lt;strong&gt;volatile&lt;/strong&gt;. That means it&apos;s constantly requiring changes. Due to that, it wouldn&apos;t be a good idea to locate logic (domain logic, specifically) that was important to other components in the architecture, because that would have the potential to consistently break the app.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Stable Dependency Principle&lt;/b&gt;: If you&apos;re interested in this phenomenon of what makes a dependency stable and what makes it unstable, check &lt;a href=&quot;/wiki/stable-dependency-principle/&quot;&gt;this&lt;/a&gt; out.&lt;/p&gt;
&lt;h3 id=&quot;Smart-and-dumb-components&quot; style=&quot;position:relative;&quot;&gt;Smart and dumb components&lt;a href=&quot;#Smart-and-dumb-components&quot; aria-label=&quot;Smart and dumb components permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Modern front-end JavaScript frameworks like React and Angular have popularized &lt;strong&gt;smart (container) components&lt;/strong&gt; and &lt;strong&gt;dumb (functional) components&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;There may be a good separation of concerns between those two, where &lt;strong&gt;smart&lt;/strong&gt; components hold the state and methods that manipulate the state, leaving &lt;strong&gt;dumb components&lt;/strong&gt; to simply project the view, but front-end is still primarily &lt;strong&gt;presentation&lt;/strong&gt; logic and should contain little to no other types of logic (besides some validation logic).&lt;/p&gt;
&lt;p&gt;To the backend, front-end is an &lt;strong&gt;infrastructural&lt;/strong&gt; concern that we provide data access / adapters to through RESTful APIs and the like.&lt;/p&gt;
&lt;h2 id=&quot;2-Data-Access--Adapter-Logic&quot; style=&quot;position:relative;&quot;&gt;2. Data Access / Adapter Logic&lt;a href=&quot;#2-Data-Access--Adapter-Logic&quot; aria-label=&quot;2 Data Access  Adapter Logic permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Logic concerned with how we enable access to infrastructure layer concern like caches, databases, front-ends, etc.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We can&apos;t get very far with just a plain ol&apos; JavaScript/TypeScript objects that represent our domain layer.&lt;/p&gt;
&lt;p&gt;We need to hook this thing up to the internet and enable a front-end to connect to it! Which web server do we want to use? Express.js? Hapi?&lt;/p&gt;
&lt;p&gt;We also need to figure out how we&apos;ll persist our domain objects. Want to use a SQL database? NoSQL? &lt;/p&gt;
&lt;p&gt;What about caching? &lt;/p&gt;
&lt;p&gt;Oh, and how do make use of cool external services like Stripe for billing or Pusher for real-time chat? We need to write adapters for those so that our inner layers can use them. &lt;/p&gt;
&lt;p&gt;That&apos;s right. This layer is all about defining the &lt;strong&gt;adapters&lt;/strong&gt; to the outside world. Simplify usage for the inner layers by encapsulating the complexity of &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;persisting an aggregate to a database&lt;/a&gt; by creating a &lt;strong&gt;Repository&lt;/strong&gt; class to do that.&lt;/p&gt;
&lt;p&gt;Here are several common things to do at this layer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RESTful APIs&lt;/strong&gt;: Define a RESTful API with Express.js and create controllers to accept requests.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Production middleware&lt;/strong&gt;:Write Express.js controller middleware to protect your API from things like DDos and brute force login attempts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Database Access&lt;/strong&gt;: Create repositories that contain methods that perform CRUD on a database. Use either an ORM like Sequelize and TypeORM or raw queries to do this.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Billing Integrations&lt;/strong&gt;: Create an adapter to a payment processor like Stripe or Paypal so that it can be used by inner layers.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;3-Application-Logic--Use-Cases&quot; style=&quot;position:relative;&quot;&gt;3. Application Logic / Use Cases&lt;a href=&quot;#3-Application-Logic--Use-Cases&quot; aria-label=&quot;3 Application Logic  Use Cases permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Logic that defines the actual features of our app&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;Use cases&lt;/a&gt; are the  features of our app.&lt;/p&gt;
&lt;p&gt;Once all the use-cases of our application have been identified and then developed, we are &lt;em&gt;objectively&lt;/em&gt; done.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Done&lt;/b&gt;: &quot;Done&quot; is a word that I don&apos;t throw around often. It has different meanings to everyone. However, we can get closer to a shared understanding of &lt;i&gt;done&lt;/i&gt; if we: figure out the use cases, and figure out who or what should be able to execute those use cases (actors or agents- because robots/servers are actors too). Once that happens, I&apos;m more confident about saying we&apos;re &lt;i&gt;done&lt;/i&gt;.&lt;/p&gt;
&lt;h3 id=&quot;CQS--CQRS&quot; style=&quot;position:relative;&quot;&gt;CQS / CQRS&lt;a href=&quot;#CQS--CQRS&quot; aria-label=&quot;CQS  CQRS permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Use Cases are either &lt;code class=&quot;language-text&quot;&gt;COMMANDS&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;QUERIES&lt;/code&gt; if we&apos;re following the &lt;a href=&quot;/articles/oop-design-principles/command-query-segregation/&quot;&gt;Command-Query Segregation&lt;/a&gt; principle.&lt;/p&gt;
&lt;h3 id=&quot;Use-Cases-are-application-specific&quot; style=&quot;position:relative;&quot;&gt;Use Cases are application specific&lt;a href=&quot;#Use-Cases-are-application-specific&quot; aria-label=&quot;Use Cases are application specific permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Your company might have several applications within it.&lt;/p&gt;
&lt;p&gt;Take Google for example. Google has &lt;strong&gt;Google Drive&lt;/strong&gt;, &lt;strong&gt;Google Docs&lt;/strong&gt;, &lt;strong&gt;Google Maps&lt;/strong&gt;, etc.&lt;/p&gt;
&lt;p&gt;Each of these applications has their own set of use cases, like this:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Google Drive&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;shareFolder(folderId: FolderId, users: UserCollection)&lt;/code&gt;: Shares a folder with other users in the Google enterprise.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;createFolder(parentFolderId: FolderId, name: string)&lt;/code&gt;: Creates a folder.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;createDocument(parentFolderId: FolderId)&lt;/code&gt;: Creates a Google Docs document.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Google Docs&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;shareDocument(users: UserCollection, visibility: VisibilityType)&lt;/code&gt;: Shares a document with several users.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;deleteDocument(documentId: DocumentId)&lt;/code&gt;: Deletes a document.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Google Maps&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;getTripRoutes (start: Location, end: Location, time?: Date)&lt;/code&gt;: Gets all routes for a trip.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;startTrip (start: Location, end: Location)&lt;/code&gt;: Starts a trip now.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A more common and simple example is deploying an &lt;strong&gt;Admin&lt;/strong&gt; panel. You might need a separate dashboard from your main app in order to do a couple of admin-y things.&lt;/p&gt;
&lt;div class=&quot;solid-book-cta course-cta&quot;&gt;
  &lt;div class=&quot;solid-book-logo-container&quot;&gt;
    &lt;img src=&quot;/img/resources/solid-book/book-logo.png&quot;/&gt;
  &lt;/div&gt;
  &lt;p&gt;I usually &lt;u&gt;plan and build software around use cases&lt;/u&gt; because it makes the code a lot easier to reason about, and &lt;u&gt;improves how rapidly&lt;/u&gt; you can complete projects.  &lt;br/&gt; &lt;br/&gt;I have a &lt;a href=&quot;/resources/names-construct-structure/&quot;&gt;free ebook&lt;/a&gt; called &quot;Name, Construct &amp; Structure&quot; where you can learn more about this approach to designing readable codebases. &lt;br/&gt; &lt;br/&gt;If you&apos;re more into the nitty-gritty of how to actually learn to code using Use-Case Driven Development, first &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;read this article on Use Cases&lt;/a&gt; (it&apos;s my favourite article).  &lt;br/&gt; &lt;br/&gt;If you want more, check out my book on &lt;a href=&quot;https://solidbook.io&quot;&gt;software design and architecture&lt;/a&gt; where I walk you through the process of Use-Case Driven Development.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;4-Domain-Service-logic&quot; style=&quot;position:relative;&quot;&gt;4. Domain Service logic&lt;a href=&quot;#4-Domain-Service-logic&quot; aria-label=&quot;4 Domain Service logic permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Core business logic that doesn&apos;t quite fit within the confines of a single entity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now we&apos;re in the &lt;strong&gt;domain layer&lt;/strong&gt;. And &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design&lt;/a&gt; is the best way to approach creating a rich domain model.&lt;/p&gt;
&lt;p&gt;In DDD, we always try to locate domain logic closest to the &lt;a href=&quot;/articles/typescript-domain-driven-design/entities/&quot;&gt;entity&lt;/a&gt; it pertains to.&lt;/p&gt;
&lt;p&gt;There comes situations where that logic spills into perhaps two or more entities, and it doesn&apos;t quite seem to make sense to locate that logic in one or the other.&lt;/p&gt;
&lt;p&gt;We use domain services to ensure that we don&apos;t lose that &lt;strong&gt;business rule&lt;/strong&gt; within one specific application&apos;s &lt;strong&gt;use case&lt;/strong&gt;, but instead keep it within the domain layer so that it can be used by every application that relies on it.&lt;/p&gt;
&lt;h2 id=&quot;5-Validation-logic&quot; style=&quot;position:relative;&quot;&gt;5. Validation logic&lt;a href=&quot;#5-Validation-logic&quot; aria-label=&quot;5 Validation logic permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Logic that dictates what it means for a domain object to be valid.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Validation logic is another &lt;strong&gt;domain layer&lt;/strong&gt; concern, not an infrastructure one.&lt;/p&gt;
&lt;p&gt;Let&apos;s say that we wanted to create a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; entity. And &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; contained a property called &lt;code class=&quot;language-text&quot;&gt;email:string&lt;/code&gt;.  &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  userEmail&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Entity&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; propsResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;againstNullOrUndefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userEmail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;propsResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;succeeded&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;propsResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What&apos;s stopping someone from creating a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; with an invalid &lt;code class=&quot;language-text&quot;&gt;userEmail:string&lt;/code&gt;?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userEmail&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;diddle&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
userOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&apos;s what we use &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;Value Objects&lt;/a&gt; for. We can encapsulate the validation rule with a &lt;strong&gt;Value Object&lt;/strong&gt; for &lt;code class=&quot;language-text&quot;&gt;userEmail&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If we change the type of &lt;code class=&quot;language-text&quot;&gt;userEmail&lt;/code&gt; to be strictly-typed instead of &lt;em&gt;string-ly&lt;/em&gt; typed like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  userEmail&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserEmail&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then create a &lt;code class=&quot;language-text&quot;&gt;UserEmail&lt;/code&gt; value object...&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; TextUtil &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../utils&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Guard &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../core&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserEmailProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserEmail&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ValueObject&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserEmailProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Private constructor. No one can say &quot;new UserEmail(&apos;diddle&apos;)&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserEmailProps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Factory method, can do UserEmail.create() &lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserEmailProps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserEmail&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;againstNullOrUndefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; 
      &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;TextUtil&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValidEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserEmail&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Email not provided or not valid.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserEmail&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, there&apos;s no way to create an invalid &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;6-Core-business-logic--entity-logic&quot; style=&quot;position:relative;&quot;&gt;6. Core business logic / entity logic&lt;a href=&quot;#6-Core-business-logic--entity-logic&quot; aria-label=&quot;6 Core business logic  entity logic permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Logic that belongs to a single entity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The most important is where the family jewels of the application are: the entity.&lt;/p&gt;
&lt;p&gt;And if the entity has a reference to other related entities, the &lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;aggregate root&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Core business logic that lives here are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Initial / default values&lt;/li&gt;
&lt;li&gt;Protecting &lt;a href=&quot;/wiki/invariant/&quot;&gt;class invariants&lt;/a&gt; (what changes are allowed, and &lt;em&gt;when&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Creating &lt;strong&gt;Domain Events&lt;/strong&gt; for changes, creations, deletions, and anything else relevant to the business. It&apos;s through domain events that complex business logic can be chained.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Some-principles-to-follow&quot; style=&quot;position:relative;&quot;&gt;Some principles to follow&lt;a href=&quot;#Some-principles-to-follow&quot; aria-label=&quot;Some principles to follow permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Never-over-engineer&quot; style=&quot;position:relative;&quot;&gt;Never over-engineer&lt;a href=&quot;#Never-over-engineer&quot; aria-label=&quot;Never over engineer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You should know when you need to use a layered architecture. Typically, it makes most sense when your application &lt;strong&gt;has a lot of business rules&lt;/strong&gt;. In that case, it&apos;s a good idea to implement a layered architecture in order to keep the concerns of &lt;strong&gt;persistence logic&lt;/strong&gt; (for example), separate from &lt;strong&gt;validation logic&lt;/strong&gt; and the &lt;strong&gt;core business rules&lt;/strong&gt; of the Domain Layer.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this article, we covered the 6 main types of logic in large application development.&lt;/p&gt;
&lt;p&gt;Here they are in summary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Presentation Logic&lt;/strong&gt;: Logic that&apos;s concerned with how we present something to the user.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data Access / Adapter Logic&lt;/strong&gt;: Logic concerned with how we enable access to infrastructure layer concern like caches, databases, front-ends, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Application Logic / Use Cases&lt;/strong&gt;: Logic that defines the actual features of our app&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Domain Service logic&lt;/strong&gt;: Core business that doesn&apos;t quite fit within the confines of a single entity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validation logic&lt;/strong&gt;: Logic that dictates what it means for a domain object to be valid.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Core business logic / entity logic&lt;/strong&gt;: Logic that belongs to a single entity.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Why I Don't Use a DI Container | Node.js w/ TypeScript]]></title><description><![CDATA[I get a lot of emails about which DI container to use. InversifyJS? Awilix? "Angular and NestJS use their own inversion of control…]]></description><link>https://khalilstemmler.com/articles/software-design-architecture/coding-without-di-container/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/software-design-architecture/coding-without-di-container/</guid><pubDate>Mon, 16 Sep 2019 04:05:26 GMT</pubDate><content:encoded>&lt;p&gt;I get a lot of emails about which DI container to use. InversifyJS? Awilix?&lt;/p&gt;
&lt;p&gt;&quot;Angular and NestJS use their own inversion of control containers, so why aren&apos;t you?&quot;&lt;/p&gt;
&lt;p&gt;Because I really haven&apos;t needed to yet. &lt;/p&gt;
&lt;p&gt;I&apos;ve been waiting for the moment where my dependencies got out of hand, so that I could honestly and sincerely see the need to utilize a DI container.&lt;/p&gt;
&lt;p&gt;But I &lt;strong&gt;haven&apos;t&lt;/strong&gt; gotten there yet.&lt;/p&gt;
&lt;p&gt;I should also add in that my primary codebase is over 150K lines of code and has been alive and actively developed on top of for about 3 years now.&lt;/p&gt;
&lt;p&gt;Although, before I learned about the Clean Architecture and &lt;a href=&quot;&quot;&gt;how to organize logic&lt;/a&gt; into layers&lt;/p&gt;
&lt;h2 id=&quot;Prerequisites&quot; style=&quot;position:relative;&quot;&gt;Prerequisites:&lt;a href=&quot;#Prerequisites&quot; aria-label=&quot;Prerequisites permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You must be &lt;em&gt;this tall&lt;/em&gt; to ride this ride.&lt;/p&gt;
&lt;p&gt;Here&apos;s some stuff you should be familiar with in with in order to join in on the conversation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Inversion of Control&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;Dependency Inversion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;Dependency Injection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;IoC Containers&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Building-a-blog&quot; style=&quot;position:relative;&quot;&gt;Building a blog&lt;a href=&quot;#Building-a-blog&quot; aria-label=&quot;Building a blog permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&apos;s imagine we&apos;re building out a website that has a &lt;strong&gt;blog&lt;/strong&gt; where you can sign up as a &lt;code class=&quot;language-text&quot;&gt;author&lt;/code&gt;, create &lt;code class=&quot;language-text&quot;&gt;posts&lt;/code&gt;, and write &lt;code class=&quot;language-text&quot;&gt;comments&lt;/code&gt; on &lt;code class=&quot;language-text&quot;&gt;posts&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;Also, assume other &lt;code class=&quot;language-text&quot;&gt;users&lt;/code&gt; can &lt;code class=&quot;language-text&quot;&gt;comment&lt;/code&gt; on your &lt;code class=&quot;language-text&quot;&gt;posts&lt;/code&gt; too.&lt;/p&gt;
&lt;p&gt;What&apos;s the first thing to do? Figure out the &lt;strong&gt;actors and the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt;&lt;/strong&gt; in order to &lt;strong&gt;package by component&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Step-1-Package-by-component&quot; style=&quot;position:relative;&quot;&gt;Step 1: Package by component&lt;a href=&quot;#Step-1-Package-by-component&quot; aria-label=&quot;Step 1 Package by component permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Front-end developers are already doing this with Angular and they might not even know it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Package by component&lt;/strong&gt; is something that Bob Martin wrote about in &lt;em&gt;Clean Architecture&lt;/em&gt; and that I wrote about in my &lt;a href=&quot;/resources/names-construct-structure/&quot;&gt;free ebook&lt;/a&gt;, &quot;Name, Construct &amp;#x26; Structure | Organizing Readable Codebases&quot;.&lt;/p&gt;
&lt;p&gt;In it, he says that we should &quot;organize our code around the Use Cases&quot; of the application. Doing that will create a project where the names of the folders practically &lt;em&gt;scream&lt;/em&gt; the domain of the problem we&apos;re solving. He calls it &quot;Screaming Architecture&quot;.&lt;/p&gt;
&lt;p&gt;Peep the folder structure for a front-end app enabling people to trade vinyl. It might look like this.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;src
  modules 
    admin             &lt;span class=&quot;token comment&quot;&gt;# Admin &quot;actor&quot; (all admin modules/components below)&lt;/span&gt;
      analytics         &lt;span class=&quot;token comment&quot;&gt;# Analytics module&lt;/span&gt;
        components/     &lt;span class=&quot;token comment&quot;&gt;# Dumb components&lt;/span&gt;
        containers      &lt;span class=&quot;token comment&quot;&gt;# Smart components&lt;/span&gt;
        pages/          &lt;span class=&quot;token comment&quot;&gt;# Pages&lt;/span&gt;
        redux/          &lt;span class=&quot;token comment&quot;&gt;# State management for this module&lt;/span&gt;
        services/       &lt;span class=&quot;token comment&quot;&gt;# API adapters&lt;/span&gt;
        styles/         &lt;span class=&quot;token comment&quot;&gt;# Styles&lt;/span&gt;
        index.ts        
      dashboard/        &lt;span class=&quot;token comment&quot;&gt;# Admin Dashboard module...&lt;/span&gt;
      users/            &lt;span class=&quot;token comment&quot;&gt;# Admin view of users module...&lt;/span&gt;
    shared/           &lt;span class=&quot;token comment&quot;&gt;# Shared (admins, traders, etc)&lt;/span&gt;
      login/            &lt;span class=&quot;token comment&quot;&gt;# Login module...&lt;/span&gt;
    traders           &lt;span class=&quot;token comment&quot;&gt;# Trader &quot;actor&quot; (all trader modules/components below)&lt;/span&gt;
      dashboard/        &lt;span class=&quot;token comment&quot;&gt;# Trader Dashboard module...&lt;/span&gt;
      register/         &lt;span class=&quot;token comment&quot;&gt;# Trader registration module...&lt;/span&gt;
      trades/           &lt;span class=&quot;token comment&quot;&gt;# Trades module...&lt;/span&gt;
  models/
  utils/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;Project structure of a Vinyl-Trading front-end app&lt;/p&gt;
&lt;p&gt;Notice that &lt;code class=&quot;language-text&quot;&gt;Admin&lt;/code&gt; has an &lt;code class=&quot;language-text&quot;&gt;analytics&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;dashboard&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;users&lt;/code&gt; module? In Angular, you&apos;re forced to export modules and link everything up using those.&lt;/p&gt;
&lt;p&gt;Angular forces you to think about &lt;strong&gt;cohesively packaging components together&lt;/strong&gt;.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;
The word &lt;i&gt;component&lt;/i&gt; can also mean module in this case (some call it &lt;b&gt;Package by Module&lt;/b&gt; instead of &lt;b&gt;Package by Component&lt;/b&gt;).
&lt;/p&gt;
&lt;p&gt;That&apos;s what I do in backend development as well.&lt;/p&gt;
&lt;p&gt;Organize code into cohesive modules... centered around the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;Structuring-the-project-around-the-use-cases&quot; style=&quot;position:relative;&quot;&gt;Structuring the project around the use cases&lt;a href=&quot;#Structuring-the-project-around-the-use-cases&quot; aria-label=&quot;Structuring the project around the use cases permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Going back to the blog, if I had to structure the project around the use cases, the folder structure would look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;src
  modules
    blog                    &lt;span class=&quot;token comment&quot;&gt;# Blog module&lt;/span&gt;
      authors               &lt;span class=&quot;token comment&quot;&gt;# Authors component&lt;/span&gt;
        domain                &lt;span class=&quot;token comment&quot;&gt;# Author module entities&lt;/span&gt;
          Author.ts
        repos                 &lt;span class=&quot;token comment&quot;&gt;# Author module repos&lt;/span&gt;
          AuthorRepo.ts
        useCases              &lt;span class=&quot;token comment&quot;&gt;# Author module use cases&lt;/span&gt;
          createAuthor                &lt;span class=&quot;token comment&quot;&gt;# &amp;lt;== Let&apos;s look at this one&lt;/span&gt;
            CreateAuthorController.ts
            CreateAuthorErrors.ts
            CreateAuthorUseCase.ts
            CreateAuthorUseCase.spec.ts
            index.ts
          getAuthorById/
          getAllAuthors/
          editAuthor/
          deleteAuthor/       
        index.ts               &lt;span class=&quot;token comment&quot;&gt;# Exports dependencies from the Authors component&lt;/span&gt;
      comments/              &lt;span class=&quot;token comment&quot;&gt;# Comments module&lt;/span&gt;
      posts/                 &lt;span class=&quot;token comment&quot;&gt;# Posts module&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;users&lt;/span&gt;                    &lt;span class=&quot;token comment&quot;&gt;# Users module&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice that the structure is similar? We&apos;re just simply following Package By Component and grouping together the features into cohesive units.&lt;/p&gt;
&lt;p&gt;Let&apos;s focus specifically on the &lt;code class=&quot;language-text&quot;&gt;CreateUser&lt;/code&gt; use case from the &lt;code class=&quot;language-text&quot;&gt;Authors&lt;/code&gt; component for now.&lt;/p&gt;
&lt;h4 id=&quot;Why-do-this&quot; style=&quot;position:relative;&quot;&gt;Why do this?&lt;a href=&quot;#Why-do-this&quot; aria-label=&quot;Why do this permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;2 reasons.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It makes it much easier to see what your code can do.&lt;/li&gt;
&lt;li&gt;People are the reason why software eventually needs to be changed. By organzing code   around the people and their use cases, it makes finding where to go to change code, trivial. Not only that, but having features segregated reduces the possibility of ripple.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;Whats-in-a-Use-Case&quot; style=&quot;position:relative;&quot;&gt;What&apos;s in a Use Case?&lt;a href=&quot;#Whats-in-a-Use-Case&quot; aria-label=&quot;Whats in a Use Case permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In any use case folder, I&apos;ll strive for &lt;strong&gt;cohesion&lt;/strong&gt; by having everything related to that use case there. That means there&apos;s a &lt;strong&gt;contoller&lt;/strong&gt;, the &lt;strong&gt;use case&lt;/strong&gt; itself, a &lt;strong&gt;test&lt;/strong&gt; for the use case, and all &lt;strong&gt;possible errors that the use case might generate&lt;/strong&gt;. I&apos;ll export what&apos;s necessary for the world outside of this module using the folder &lt;code class=&quot;language-text&quot;&gt;index.ts&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;authors
  domain/
  repos/
  useCases              &lt;span class=&quot;token comment&quot;&gt;# Author module use cases&lt;/span&gt;
    createAuthor                
      CreateAuthorController.ts     &lt;span class=&quot;token comment&quot;&gt;# Application controller&lt;/span&gt;
      CreateAuthorErrors.ts         &lt;span class=&quot;token comment&quot;&gt;# Errors namespace&lt;/span&gt;
      CreateAuthorUseCase.ts        &lt;span class=&quot;token comment&quot;&gt;# Use case&lt;/span&gt;
      CreateAuthorUseCase.spec.ts   &lt;span class=&quot;token comment&quot;&gt;# Test for the use case&lt;/span&gt;
      index.ts                      &lt;span class=&quot;token comment&quot;&gt;# Compose and export use case + controller&lt;/span&gt;
    getAuthorById/
    getAllAuthors/
    editAuthor/
    deleteAuthor/  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;Errors&quot; style=&quot;position:relative;&quot;&gt;Errors&lt;a href=&quot;#Errors&quot; aria-label=&quot;Errors permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Using a TypeScript namespace, I can represent all the errors for this use case.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;CreateAuthorErrors.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Result &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;core/Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; DomainError &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;core/DomainErrror&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; CreateAuthorErrors &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AuthorExistsError&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;DomainError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Author already exists&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; DomainError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserNotYetCreatedError&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;DomainError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Need to create the user account first&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; DomainError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;Use-Case&quot; style=&quot;position:relative;&quot;&gt;Use Case&lt;a href=&quot;#Use-Case&quot; aria-label=&quot;Use Case permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The use case contains the actual feature. &lt;/p&gt;
&lt;p&gt;For this particular use case, the &lt;code class=&quot;language-text&quot;&gt;CreateAuthorUseCase&lt;/code&gt;, it relies on &lt;strong&gt;two external dependencies&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;One of them, the &lt;code class=&quot;language-text&quot;&gt;IAuthorRepo&lt;/code&gt;, is from the &lt;code class=&quot;language-text&quot;&gt;authors&lt;/code&gt; module.&lt;/p&gt;
&lt;p&gt;The other one, the &lt;code class=&quot;language-text&quot;&gt;IUserRepo&lt;/code&gt;, is from the &lt;code class=&quot;language-text&quot;&gt;users&lt;/code&gt; module. &lt;/p&gt;
&lt;p&gt;It also utilizes &lt;a href=&quot;/articles/enterprise-typescript-nodejs/functional-error-handling/&quot;&gt;functional error handling techniques&lt;/a&gt; that we explored in a previous article.&lt;/p&gt;
&lt;p&gt;Take a look:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;CreateAuthorUseCase.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UseCase &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;core/UseCase&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Either&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; left&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; right &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;core/Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CreateAuthorErrors &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./CreateAuthorErrors&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AppError &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;core/AppError&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IUserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;modules/users/repos/UserRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IAuthorRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../repos/AuthorRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Author &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../domain/Author&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// All we need to execute this is a userId: string.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// The response is going to be either one of these&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// failure states, or a Result&amp;lt;void&gt; if successful.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
  CreateAuthorErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AuthorExistsError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  CreateAuthorErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UserNotYetCreatedError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  AppError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UnexpectedError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateAuthorUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Response&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// This use case relies on an IUserRepo and an IAuthorRepo to work&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; authorRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IAuthorRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; authorRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IAuthorRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;authorRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; authorRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Response&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUserById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userExists &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// If the user doesn&apos;t exist yet, we can&apos;t make them an author&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;userExists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateAuthorErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UserNotYetCreatedError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// If the user was already made an author, we can return a failed result.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; alreadyCreatedAuthor &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;authorRepo
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAuthorByUserId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;alreadyCreatedAuthor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateAuthorErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AuthorExistsError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// If validation logic fails to create an author, we can return a failed result&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; authorOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Author&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Author
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;authorOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AppError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UnexpectedError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;authorOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


    &lt;span class=&quot;token comment&quot;&gt;// Save the author to the repo&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; author &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; authorOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;authorRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;author&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Successfully created the author&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;Controller&quot; style=&quot;position:relative;&quot;&gt;Controller&lt;a href=&quot;#Controller&quot; aria-label=&quot;Controller permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;While the controller may be an &lt;a href=&quot;/articles/software-design-architecture/organizing-app-logic/&quot;&gt;infrastructure adapter&lt;/a&gt;, we still want to couple it with the use case to keep this module cohesive.&lt;/p&gt;
&lt;p&gt;The controller has one dependency, and it&apos;s the &lt;code class=&quot;language-text&quot;&gt;CreateAuthorUseCase&lt;/code&gt; from this module.&lt;/p&gt;
&lt;p&gt;We will need to compose the controller with that as a dependency in order to create an instance of this controller.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Base controller&lt;/b&gt;: We&apos;re using the &lt;b&gt;BaseController&lt;/b&gt; from &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-consistent-expressjs-controllers/&quot;&gt;this guide&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;CreateAuthorController.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CreateAuthorUseCase &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./CreateAuthorUseCase&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AppError &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;core/AppError&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CreateAuthorErrors &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./CreateAuthorErrors&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateAuthorController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; useCase&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CreateAuthorUseCase&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;useCase&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CreateAuthorUseCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;useCase &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; useCase&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeImpl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; req &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;req &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; DecodedExpressRequest&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;decoded&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;useCase&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isLeft&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; error &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Based on the error, map to the appropriate HTTP code&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; CreateAuthorErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AuthorExistsError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;notFound&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;errorValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; CreateAuthorErrors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UserNotYetCreatedError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;errorValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; AppError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UnexpectedError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;errorValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Something went wrong on our end.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We have everything we need in order to execute this feature.&lt;/p&gt;
&lt;p&gt;We just need to hook it up.&lt;/p&gt;
&lt;a href=&quot;/resources/names-construct-structure/&quot;&gt;
  &lt;img src=&quot;/img/banner/ncs-banner.png&quot;/&gt;
&lt;/a&gt;
&lt;h2 id=&quot;Step-2-Create-and-export-features-from-module&quot; style=&quot;position:relative;&quot;&gt;Step 2: Create and export features from module&lt;a href=&quot;#Step-2-Create-and-export-features-from-module&quot; aria-label=&quot;Step 2 Create and export features from module permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Recall that the folder structure looks like this.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;authors
  domain/
  repos/
  useCases              &lt;span class=&quot;token comment&quot;&gt;# Author module use cases&lt;/span&gt;
    createAuthor                
      CreateAuthorController.ts     &lt;span class=&quot;token comment&quot;&gt;# Application controller&lt;/span&gt;
      CreateAuthorErrors.ts         &lt;span class=&quot;token comment&quot;&gt;# Errors namespace&lt;/span&gt;
      CreateAuthorUseCase.ts        &lt;span class=&quot;token comment&quot;&gt;# Use case&lt;/span&gt;
      CreateAuthorUseCase.spec.ts   &lt;span class=&quot;token comment&quot;&gt;# Test for the use case&lt;/span&gt;
      index.ts                      &lt;span class=&quot;token comment&quot;&gt;# Compose and export use case + controller&lt;/span&gt;
    getAuthorById/
    getAllAuthors/
    editAuthor/
    deleteAuthor/  
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
users/
  &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first thing to create is the &lt;code class=&quot;language-text&quot;&gt;CreateAuthorUseCase&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But &lt;code class=&quot;language-text&quot;&gt;CreateAuthorUseCase&lt;/code&gt; relies on some dependencies (&lt;code class=&quot;language-text&quot;&gt;IUserRepo&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;IAuthorRepo&lt;/code&gt;).&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;author/useCases/createAuthor/index.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CreateAuthorUseCase &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./CreateAuthorUseCase&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; createAuthorUseCase &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateAuthorUseCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* An argument 
for &apos;userRepo&apos; and &apos;authorRepo&apos; was not provided. */&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;My &lt;strong&gt;style guide&lt;/strong&gt; for exporting dependencies is this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Always use &lt;code class=&quot;language-text&quot;&gt;index.ts&lt;/code&gt; to export what needs to be used by others from your module.&lt;/li&gt;
&lt;li&gt;Always use lowercase names to signal that an exported dependency is an instance, not a class.&lt;/li&gt;
&lt;li&gt;Only &lt;u&gt;export&lt;/u&gt; dependencies from the direct parent folder. Only &lt;code class=&quot;language-text&quot;&gt;users/repos/index.ts&lt;/code&gt; is allowed to export &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt;, because it resides as &lt;code class=&quot;language-text&quot;&gt;users/repos/UserRepo.ts&lt;/code&gt;. &lt;code class=&quot;language-text&quot;&gt;users/index.ts&lt;/code&gt; (or anywhere else) is not allowed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Over in the &lt;code class=&quot;language-text&quot;&gt;users&lt;/code&gt; module, I would have exported an instance of an &lt;code class=&quot;language-text&quot;&gt;IUserRepo&lt;/code&gt; as &lt;code class=&quot;language-text&quot;&gt;userRepo&lt;/code&gt; like this:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;modules/users/repos/index.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; models &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../../core/infra/models&apos;&lt;/span&gt; 
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./UserRepo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
  userRepo
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then I would have imported it into the &lt;code class=&quot;language-text&quot;&gt;authors/useCases/index.ts&lt;/code&gt; which is generally a &lt;strong&gt;great experience&lt;/strong&gt; using Visual Studio Code&apos;s intellisense.&lt;/p&gt;
&lt;div style=&quot;width:100%;height:0;padding-bottom:49%;position:relative;&quot;&gt;&lt;iframe src=&quot;https://giphy.com/embed/lS1SkwJC9gyTwk0pOh&quot; width=&quot;100%&quot; height=&quot;100%&quot; style=&quot;position:absolute&quot; frameBorder=&quot;0&quot; class=&quot;giphy-embed&quot; allowFullScreen&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&quot;https://giphy.com/gifs/lS1SkwJC9gyTwk0pOh&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Using Intellisense to automatically trace dependencies by name.&lt;/p&gt;
&lt;p&gt;Nice. Now that the use case is created, I need to inject &lt;em&gt;that&lt;/em&gt; into my controller.&lt;/p&gt;
&lt;p&gt;Once that&apos;s done, I&apos;ll export them both from this module.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;author/useCases/createAuthor/index.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CreateAuthorUseCase &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./CreateAuthorUseCase&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;modules/users/repos&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; authorRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../repos&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CreateAuthorController &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./CreateAuthorController&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; createAuthorUseCase &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateAuthorUseCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  userRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; authorRepo
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Inject the use case into the controller to create it&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; createAuthorController &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateAuthorController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  createAuthorUseCase
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Export instances as lowercase to signify they&apos;re instances&lt;/span&gt;
  createAuthorUseCase&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  createAuthorController
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Using-the-Use-Case-Features&quot; style=&quot;position:relative;&quot;&gt;Using the Use Case Features&lt;a href=&quot;#Using-the-Use-Case-Features&quot; aria-label=&quot;Using the Use Case Features permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now, if I want to use the &lt;code class=&quot;language-text&quot;&gt;CreateAuthorUseCase&lt;/code&gt;, all I have to do is start typing &lt;code class=&quot;language-text&quot;&gt;createAuthor...&lt;/code&gt; and I&apos;ll be shown both the &lt;code class=&quot;language-text&quot;&gt;CreateAuthorUseCase&lt;/code&gt; in addition to the &lt;code class=&quot;language-text&quot;&gt;CreateAuthorUseCaseController&lt;/code&gt; instances.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
  createAuthorUseCaseController 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &apos;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;modules&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;author&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;useCases&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;createAuthor`

&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; authorRouter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Router&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

authorRouter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; createAuthorUseCaseController&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Benefits-of-not-using-a-DI-container&quot; style=&quot;position:relative;&quot;&gt;Benefits of not using a DI container&lt;a href=&quot;#Benefits-of-not-using-a-DI-container&quot; aria-label=&quot;Benefits of not using a DI container permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Less-complexity&quot; style=&quot;position:relative;&quot;&gt;Less complexity&lt;a href=&quot;#Less-complexity&quot; aria-label=&quot;Less complexity permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Just use the module system! Node.js automatically makes everything a singleton the first time it&apos;s imported, if that matters to you.&lt;/p&gt;
&lt;h3 id=&quot;Better-software-composition&quot; style=&quot;position:relative;&quot;&gt;Better software composition&lt;a href=&quot;#Better-software-composition&quot; aria-label=&quot;Better software composition permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Not using a DI container forces you to understand how you compose your classes a lot better, rather than just creating a new &lt;code class=&quot;language-text&quot;&gt;CatsService&lt;/code&gt; with an injectable decorator on it.&lt;/p&gt;
&lt;p&gt;This is exactly the type of thing that &lt;a href=&quot;https://leanpub.com/composingsoftware&quot;&gt;Eric Elliot&lt;/a&gt; has written about extensively in his &lt;strong&gt;Composing Software&lt;/strong&gt; book.&lt;/p&gt;
&lt;h3 id=&quot;Less-circular-dependencies&quot; style=&quot;position:relative;&quot;&gt;Less circular dependencies&lt;a href=&quot;#Less-circular-dependencies&quot; aria-label=&quot;Less circular dependencies permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Not using a DI container makes it very hard for you to introduce circular dependencies because you have a better understanding of what is being exported and imported, and in what order. You&apos;re forced to compose software components together.&lt;/p&gt;
&lt;p&gt;This is how stuff stays testable.&lt;/p&gt;
&lt;h3 id=&quot;Less-decorator-noise&quot; style=&quot;position:relative;&quot;&gt;Less decorator noise&lt;a href=&quot;#Less-decorator-noise&quot; aria-label=&quot;Less decorator noise permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Decorators are low-level details that makes it&apos;s way into your application level code. I&apos;d argue that that&apos;s not very clean.&lt;/p&gt;
&lt;h2 id=&quot;Disadvantages&quot; style=&quot;position:relative;&quot;&gt;Disadvantages&lt;a href=&quot;#Disadvantages&quot; aria-label=&quot;Disadvantages permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Working-on-teams&quot; style=&quot;position:relative;&quot;&gt;Working on teams&lt;a href=&quot;#Working-on-teams&quot; aria-label=&quot;Working on teams permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I think working on teams is sometimes more challenging than working with yourself.&lt;/p&gt;
&lt;p&gt;The reasons why frameworks like Angular and NestJS are nodded towards for enterprise software more often than tools like React and Vue, is because frameworks &lt;strong&gt;are opinionated&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;Frameworks tell you how to do things- their way and their way only. &lt;/p&gt;
&lt;p&gt;There is exactly one way to create a Route Guard in Angular.&lt;/p&gt;
&lt;p&gt;In React, that&apos;s a different story.&lt;/p&gt;
&lt;p&gt;When working with several other people on a team, it can be very challenging to get everyone to adhere to a style guide and do things a certain way, like package features into cohesive components.&lt;/p&gt;
&lt;p&gt;Frameworks are successful here because they &lt;u&gt;reduce the total surface area of ways you can do something&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;But if the team is small, disciplined, and the experience level is similar, I think that it can work.&lt;/p&gt;
&lt;h3 id=&quot;Everyone-needs-to-follow-the-style-guide&quot; style=&quot;position:relative;&quot;&gt;Everyone needs to follow the style guide&lt;a href=&quot;#Everyone-needs-to-follow-the-style-guide&quot; aria-label=&quot;Everyone needs to follow the style guide permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is what works for me! Like any project style guide, other developers working within the codebase need to adopt it.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[No title]]></title><description><![CDATA[If a component is really stable, it's likely it's going to be serving more purposes for more groups of people, and for different problems…]]></description><link>https://khalilstemmler.com/wiki/stable-abstraction-principle/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/stable-abstraction-principle/</guid><pubDate>Sun, 15 Sep 2019 04:05:28 GMT</pubDate><content:encoded>&lt;p&gt;If a component is really stable, it&apos;s likely it&apos;s going to be serving more purposes for more groups of people, and for different problems.&lt;/p&gt;
&lt;p&gt;In order to prevent a component from becoming too specific or rigid, we should primarily use abstract classes. &lt;/p&gt;
&lt;p&gt;Abstract classes work well for &lt;em&gt;defining the high-level policy&lt;/em&gt; and leaving room for various implementations of the low-level details.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Reference: &lt;a href=&quot;https://blog.cleancoder.com/&quot;&gt;https://blog.cleancoder.com/&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[No title]]></title><description><![CDATA[Every system has stable components and volatile components. Stable components are components that aren't expected to change that often…]]></description><link>https://khalilstemmler.com/wiki/stable-dependency-principle/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/stable-dependency-principle/</guid><pubDate>Sun, 15 Sep 2019 04:05:27 GMT</pubDate><content:encoded>&lt;p&gt;Every system has &lt;strong&gt;stable&lt;/strong&gt; components and &lt;strong&gt;volatile&lt;/strong&gt; components.&lt;/p&gt;
&lt;p&gt;Stable components are components that aren&apos;t expected to change that often. &lt;/p&gt;
&lt;p&gt;They either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Contain high-level policy, OR&lt;/li&gt;
&lt;li&gt;Have stood the test of time, and the component has more or less found it&apos;s role within the architecture. All likely use cases that would influence change within the component have been identified and addressed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because of this fact, it&apos;s more often that we&apos;ll write code that depends on stable components.&lt;/p&gt;
&lt;p&gt;Volatile components are ones that are more likely to jitter and require frequent changes.&lt;/p&gt;
&lt;p&gt;This is because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They are low-level details&lt;/li&gt;
&lt;li&gt;They are fairly new and all of the likely use cases that would influence change within the component have &lt;em&gt;not yet&lt;/em&gt; been identified.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There&apos;s nothing wrong with volatile components, every system has them and that&apos;s perfectly fine. &lt;/p&gt;
&lt;p&gt;But it&apos;s important to know when a component is volatile and ensure that we &lt;u&gt;don&apos;t make stable components depend on them&lt;/u&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Examples-of-stable-components&quot; style=&quot;position:relative;&quot;&gt;Examples of stable components&lt;a href=&quot;#Examples-of-stable-components&quot; aria-label=&quot;Examples of stable components permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ECMAScript approved language constructs: &lt;code class=&quot;language-text&quot;&gt;Number.toFixed()&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;JSON.stringify()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Higher-level policies like domain-layer classes: &lt;a href=&quot;/articles/typescript-domain-driven-design/entities/&quot;&gt;entities&lt;/a&gt;, &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;value objects&lt;/a&gt;, &lt;a href=&quot;/blogs/domain-driven-design/where-do-domain-events-get-dispatched/&quot;&gt;domain events&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;GraphQL schemas: the client-side relies on it, and the service-side implements it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Examples-of-volatile-components&quot; style=&quot;position:relative;&quot;&gt;Examples of volatile components&lt;a href=&quot;#Examples-of-volatile-components&quot; aria-label=&quot;Examples of volatile components permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Front ends. Architecturally, front-end applications are very volatile compared to backend services. The styles, layout, html, css, etc are constantly being changed. This makes  testing on the client-side challenging and often times fruitless. When writing Cypress.io or Selenium tests, best practices dictate to refrain from writing tests that rely on the implementation details (styles, css tags, ids, pixels, etc). Instead, work to verify correctness by testing against the &lt;em&gt;behaviour&lt;/em&gt;. Even with our best efforts, unless an application has completely converged, it&apos;s more likely that behaviour on the client-side will change, requiring tests to constantly need to be rewritten.&lt;/li&gt;
&lt;li&gt;Classes with no clear &lt;a href=&quot;/articles/solid-principles/single-responsibility/&quot;&gt;single responsibility&lt;/a&gt;. Change originates from the actors/roles that rely on a component. The more actors/roles that rely on a component, the more reasons it has to change. If more than one actor/role relies on a component (or we&apos;re not sure who owns it), the component is said to have &lt;em&gt;no singular responsibility&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;Reference: &lt;a href=&quot;https://blog.cleancoder.com/&quot;&gt;https://blog.cleancoder.com/&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[No title]]></title><description><![CDATA[In the header image, component A relies on component B which relies on component C. The problem is that component C also relies on A. That…]]></description><link>https://khalilstemmler.com/wiki/acyclic-dependencies-principle/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/acyclic-dependencies-principle/</guid><pubDate>Sun, 15 Sep 2019 04:05:26 GMT</pubDate><content:encoded>&lt;p&gt;In the header image, component A relies on component B which relies on component C.&lt;/p&gt;
&lt;p&gt;The problem is that component C also relies on A.&lt;/p&gt;
&lt;p&gt;That creates a cycle.&lt;/p&gt;
&lt;p&gt;We don&apos;t want dependency cycles because they:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make the code hard to understand, thus reducing maintainability&lt;/li&gt;
&lt;li&gt;Reduce the quality of the code and improve the likelihood of errors by making it harder to change one component without affecting another&lt;/li&gt;
&lt;li&gt;Make it impossible to test each individual component because they can&apos;t be separated&lt;/li&gt;
&lt;li&gt;Have the ability to violate &lt;a href=&quot;/wiki/dependency-rule/&quot;&gt;The Dependency Rule&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following example demonstrates a violation of ADP. A cycle exists where &lt;code class=&quot;language-text&quot;&gt;UsernameGenerator&lt;/code&gt; relies on &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt;, which relies on &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;, which relies on &lt;code class=&quot;language-text&quot;&gt;UsernameGenerator&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/wiki/package-principles/bad-cycle-example.svg&quot; alt=&quot;Dependency graph with a Cycle&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;How-to-fix-it&quot; style=&quot;position:relative;&quot;&gt;How to fix it?&lt;a href=&quot;#How-to-fix-it&quot; aria-label=&quot;How to fix it permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Two ways:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;/articles/tutorials/dependency-injection-inversion-explained&quot;&gt;Dependency Inversion&lt;/a&gt;. Stick an interface inbetween one of the relationships to &lt;strong&gt;break the cycle&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Rethink your layers. If you&apos;ve run into cycles like this, it might be a good signal that you&apos;re not following &lt;a href=&quot;/wiki/dependency-rule/&quot;&gt;The Dependency Rule&lt;/a&gt;. You can fix that by aiming to understand and separate the concerns of your application into layers. See &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;The Clean Architecture&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;i-classfas-fa-exchange-alti-Other-related-topics&quot; style=&quot;position:relative;&quot;&gt;&lt;i class=&quot;fas fa-exchange-alt&quot;&gt;&lt;/i&gt; Other related topics&lt;a href=&quot;#i-classfas-fa-exchange-alti-Other-related-topics&quot; aria-label=&quot;i classfas fa exchange alti Other related topics permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Dependency-Inversion-Principle&quot; style=&quot;position:relative;&quot;&gt;Dependency Inversion Principle&lt;a href=&quot;#Dependency-Inversion-Principle&quot; aria-label=&quot;Dependency Inversion Principle permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is how we might be able to break a dependency cycle.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;Check out &lt;a href=&quot;/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;this article&lt;/a&gt;, &quot;Dependency Injection &amp; Inversion Explained | Node.js w/ TypeScript&quot;.&lt;/p&gt;
&lt;h3 id=&quot;The-Dependency-Rule&quot; style=&quot;position:relative;&quot;&gt;The Dependency Rule&lt;a href=&quot;#The-Dependency-Rule&quot; aria-label=&quot;The Dependency Rule permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The direction of dependencies should form an &lt;em&gt;acyclic&lt;/em&gt; graph where the lower-level components always &lt;strong&gt;rely on/point towards&lt;/strong&gt; the higher-level policy.&lt;/p&gt;
&lt;p&gt;For example, given the following generic application architecture, notice that all of the outer layer details point towards the inner-layer ones (Domain layer + Application layer)?&lt;/p&gt;
&lt;img style=&quot;width: 100%;&quot; src=&quot;/img/blog/ddd-frontend/generic-application-architecture.svg&quot;/&gt;
&lt;p&gt;That&apos;s how you follow the &lt;strong&gt;dependency rule&lt;/strong&gt;.&lt;/p&gt;
&lt;img style=&quot;width: 100%;&quot; src=&quot;/img/blog/ddd-frontend/component-volatility.svg&quot;/&gt;
&lt;hr&gt;
&lt;p&gt;Reference: &lt;a href=&quot;https://blog.cleancoder.com/&quot;&gt;https://blog.cleancoder.com/&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Dependency Injection & Inversion Explained | Node.js w/ TypeScript]]></title><description><![CDATA[One of the first things we learn in programming is to decompose large problems into smaller parts. That divide-and-conquer approach can help…]]></description><link>https://khalilstemmler.com/articles/tutorials/dependency-injection-inversion-explained/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/tutorials/dependency-injection-inversion-explained/</guid><pubDate>Wed, 11 Sep 2019 15:04:10 GMT</pubDate><content:encoded>&lt;div class=&quot;solid-book-cta course-cta&quot;&gt;
  &lt;div class=&quot;solid-book-logo-container&quot;&gt;
    &lt;img src=&quot;/img/resources/solid-book/book-logo.png&quot;/&gt;
  &lt;/div&gt;
  &lt;p&gt;This topic is taken from Solid Book - The Software Architecture &amp; Design Handbook w/ TypeScript + Node.js. &lt;a href=&quot;https://solidbook.io&quot;&gt;Check it out&lt;/a&gt; if you like this post.&lt;/p&gt;
&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;Translated by readers to: &lt;a href=&quot;https://dev.to/oieduardorabelo/um-guia-sobre-injecao-e-inversao-de-dependencias-em-node-js-e-typescript-1bod&quot;&gt;Brazilian Portuguese&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;One of the first things we learn in programming is to decompose large problems into smaller parts. That divide-and-conquer approach can help us to assign tasks to others, reduce anxiety by focusing on one thing at a time, and improve modularity of our designs.&lt;/p&gt;
&lt;p&gt;But there comes a time when things are ready to be hooked up. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;That&apos;s where most developers go about things the wrong way.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Most developers that haven&apos;t yet learned about the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;solid principles&lt;/a&gt; or software composition, and proceed to write tightly couple modules and classes that shouldn&apos;t be coupled, resulting in code that&apos;s &lt;strong&gt;hard to change&lt;/strong&gt; and &lt;strong&gt;hard to test&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In this article, we&apos;re going to learn about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Components &amp;#x26; software composition&lt;/li&gt;
&lt;li&gt;How NOT to hook up components&lt;/li&gt;
&lt;li&gt;How and why to inject dependencies using Dependency Injection&lt;/li&gt;
&lt;li&gt;How to apply Dependency Inversion and write testable code&lt;/li&gt;
&lt;li&gt;Considerations using Inversion of Control containers&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Terminology&quot; style=&quot;position:relative;&quot;&gt;Terminology&lt;a href=&quot;#Terminology&quot; aria-label=&quot;Terminology permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&apos;s make sure that we understand the terminology on wiring up dependencies before we continue.&lt;/p&gt;
&lt;h3 id=&quot;Components&quot; style=&quot;position:relative;&quot;&gt;Components&lt;a href=&quot;#Components&quot; aria-label=&quot;Components permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&apos;m going to use the term &lt;strong&gt;component&lt;/strong&gt; a lot. That term might strike a chord with React.js or Angular developers, but it can be used beyond the scope of web, Angular, or React. &lt;/p&gt;
&lt;p&gt;A component is simply a &lt;strong&gt;part of an application&lt;/strong&gt;. It&apos;s any group of software that&apos;s intended to be a part of a larger system.&lt;/p&gt;
&lt;p&gt;The idea is to break a &lt;em&gt;large application&lt;/em&gt;  up into several modular components that can be independently developed and assembled.&lt;/p&gt;
&lt;p&gt;The more you learn about software, the more you realize that good software design is &lt;strong&gt;all about composition&lt;/strong&gt; of components.&lt;/p&gt;
&lt;p&gt;Failure to get this right leads to &lt;em&gt;clumpy&lt;/em&gt; code that can&apos;t be tested.&lt;/p&gt;
&lt;h3 id=&quot;Dependency-Injection&quot; style=&quot;position:relative;&quot;&gt;Dependency Injection&lt;a href=&quot;#Dependency-Injection&quot; aria-label=&quot;Dependency Injection permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Eventually, we&apos;ll need to hook components up somehow. Let&apos;s look at a trivial (and non-ideal) way that we might hook two components up together. &lt;/p&gt;
&lt;p&gt;In the following example, we want to hook up a &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt; so that it can retrieve all the &lt;code class=&quot;language-text&quot;&gt;User[]&lt;/code&gt;s from a &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; (&lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;repository&lt;/a&gt;) when someone makes an HTTP GET request to &lt;code class=&quot;language-text&quot;&gt;/api/users&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;repos/userRepo.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/**
 * @class UserRepo
 * @desc Responsible for pulling users from persistence.
 **/&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getUsers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Use Sequelize or TypeORM to retrieve the users from&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// a database.&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And the controller...&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;controllers/userController.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../repos&apos;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Bad&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * @class UserController
 * @desc Responsible for handling API requests for the
 * /user route.
 **/&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Also bad, read on for why&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleGetUsers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; users &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUsers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; users &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the example, we connected a &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; directly to a &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt; by &lt;u&gt;referencing the name&lt;/u&gt; of the &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; class from within the &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;This isn&apos;t ideal. When we do that, we create a &lt;strong&gt;source code dependency&lt;/strong&gt;. &lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Source code dependency&lt;/b&gt;: When the current component (class, module, etc) relies on at least one other component &lt;u&gt;in order to be compiled&lt;/u&gt;. Source code depdendencies should be limited.&lt;/p&gt;
&lt;p&gt;The problem is that everytime that we want to spin up a &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt;, we need to make sure that the &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; is also &lt;u&gt;within reach&lt;/u&gt; so that the code can compile. &lt;/p&gt;
&lt;img style=&quot;width: 100%;&quot; src=&quot;/img/blog/di-container/before-dependency-inversion.svg&quot;&gt;
&lt;p class=&quot;caption&quot;&gt;The UserController class depends directly on the UserRepo class.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;When might you want to spin up an isolated &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt;?&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;During testing.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;It&apos;s a common practice during testing to &lt;i&gt;mock&lt;/i&gt; or &lt;i&gt;fake&lt;/i&gt; dependencies of the &lt;b&gt;current module under test&lt;/b&gt; in order to isolate and test different behaviors.&lt;/p&gt;
&lt;p&gt;Notice how we&apos;re a) importing the &lt;a href=&quot;/wiki/concrete-class/&quot;&gt;concrete&lt;/a&gt; &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; class into the file and b) creating an instance of it from within the &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt; constructor?&lt;/p&gt;
&lt;p&gt;That renders this code &lt;strong&gt;untestable&lt;/strong&gt;. Or at least, if &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; was connected to a real live running database, we&apos;d have to &lt;b&gt;bring the entire database connection&lt;/b&gt; with us to run our tests, making them very slow...&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Dependency Injection&lt;/strong&gt; is a technique that can improve the testability of our code. &lt;/p&gt;
&lt;p&gt;It works by passing in (usually via constructor) the dependencies that your module needs to operate. &lt;/p&gt;
&lt;p&gt;If we change the way we inject the &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; from &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt;, we can improve it slightly.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;controllers/userController.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../repos&apos;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Still bad&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * @class UserController
 * @desc Responsible for handling API requests for the
 * /user route.
 **/&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Better, inject via constructor&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleGetUsers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; users &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUsers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; users &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Even though we&apos;re using dependency injection, there&apos;s still a problem.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt; still relies on &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; &lt;em&gt;directly&lt;/em&gt;.&lt;/p&gt;
&lt;img style=&quot;width: 100%;&quot; src=&quot;/img/blog/di-container/before-dependency-inversion.svg&quot;&gt;
&lt;p class=&quot;caption&quot;&gt;This dependency relationship still holds true.&lt;/p&gt;
&lt;p&gt;Even still, if we wanted to mock out our &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; that connects to a real SQL database for a mock &lt;strong&gt;in-memory repository&lt;/strong&gt;, it&apos;s not currently possible.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt; needs a &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt;, specifically.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;controllers/userRepo.spec.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; userController&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserController&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;beforeEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  userController &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Slows down tests, needs a db running&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So.. what do we do?&lt;/p&gt;
&lt;p&gt;Introducing the &lt;strong&gt;Dependency &lt;em&gt;Inversion&lt;/em&gt; Principle&lt;/strong&gt;!&lt;/p&gt;
&lt;h3 id=&quot;Dependency-Inversion&quot; style=&quot;position:relative;&quot;&gt;Dependency Inversion&lt;a href=&quot;#Dependency-Inversion&quot; aria-label=&quot;Dependency Inversion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Dependency Inversion is a technique that allows us to &lt;strong&gt;decouple&lt;/strong&gt; components from one another. Check this out.&lt;/p&gt;
&lt;p&gt;What direction does the &lt;strong&gt;flow of dependencies&lt;/strong&gt; go in right now? &lt;/p&gt;
&lt;img style=&quot;width: 100%;&quot; src=&quot;/img/blog/di-container/before-dependency-inversion.svg&quot;&gt;
&lt;p&gt;From left to right. The &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt; relies on the &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;OK. Ready?&lt;/p&gt;
&lt;p&gt;Watch what happens when we &lt;del&gt;slap an interface in between the two components&lt;/del&gt; make &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; implement an &lt;code class=&quot;language-text&quot;&gt;IUserRepo&lt;/code&gt; interface, and then point the &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt; to refer to &lt;em&gt;that&lt;/em&gt; instead of the &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; concrete class.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;repos/userRepo.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/**
 * @interface IUserRepo
 * @desc Responsible for pulling users from persistence.
 **/&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IUserRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;          &lt;span class=&quot;token comment&quot;&gt;// Exported&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getUsers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IUserRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Not exported&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getUsers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And update the controller to refer to the &lt;code class=&quot;language-text&quot;&gt;IUserRepo&lt;/code&gt; interface &lt;em&gt;instead&lt;/em&gt; of the &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; concrete class.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;controllers/userController.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IUserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../repos&apos;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Good!&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * @class UserController
 * @desc Responsible for handling API requests for the
 * /user route.
 **/&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// like here&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// and here&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleGetUsers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; users &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUsers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; users &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Now&lt;/em&gt; look at direction of the flow of dependencies.&lt;/p&gt;
&lt;img style=&quot;width: 100%;&quot; src=&quot;/img/blog/di-container/after-dependency-inversion.svg&quot;&gt;
&lt;p&gt;You see what we just did? By changing all of the &lt;strong&gt;references from concrete classes to interfaces&lt;/strong&gt;, we&apos;ve just &lt;strong&gt;flipped the dependency graph&lt;/strong&gt; and created an &lt;em&gt;architectural boundary&lt;/em&gt; inbetween the two components.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Design principle&lt;/b&gt;: Program against interfaces, not implementations.&lt;/p&gt;
&lt;p&gt;Maybe you&apos;re not as excited about this as I am. Let me show you why this is so great.&lt;/p&gt;
&lt;div class=&quot;solid-book-cta course-cta&quot;&gt;
  &lt;div class=&quot;solid-book-logo-container&quot;&gt;
    &lt;img src=&quot;/img/resources/solid-book/book-logo.png&quot;/&gt;
  &lt;/div&gt;
  &lt;p&gt;And if you like this article so far, you might like my book, &quot;Solid - The Software Architecture &amp; Design Handbook w/ TypeScript + Node.js&quot;. You&apos;ll learn how to write testable, flexible, and maintainable code using principles (like this one) that I think all professional people in software should know about. &lt;a href=&quot;https://solidbook.io&quot;&gt;Check it out&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Remember when I said that we wanted to be able to run tests on the &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt; without having to pass in a &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt;, solely because it would make the tests slow(&lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; needs a db connection to run)?&lt;/p&gt;
&lt;p&gt;Well, now we &lt;u&gt;can write a &lt;code class=&quot;language-text&quot;&gt;MockUserRepo&lt;/code&gt;&lt;/u&gt; which implements &lt;code class=&quot;language-text&quot;&gt;IUserRepo&lt;/code&gt; and all the methods on the interface, and instead of using a class that relies on a slow db connection, use a class that contains an internal array of &lt;code class=&quot;language-text&quot;&gt;User[]&lt;/code&gt;s (much quicker! ⚡).&lt;/p&gt;
&lt;p&gt;That&apos;s what we&apos;ll pass that into the &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt; instead.&lt;/p&gt;
&lt;h3 id=&quot;Using-a-MockUserRepo-to-mock-out-our-UserController&quot; style=&quot;position:relative;&quot;&gt;Using a &lt;code class=&quot;language-text&quot;&gt;MockUserRepo&lt;/code&gt; to mock out our &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt;&lt;a href=&quot;#Using-a-MockUserRepo-to-mock-out-our-UserController&quot; aria-label=&quot;Using a MockUserRepo to mock out our UserController permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;filename&quot;&gt;repos/mocks/mockUserRepo.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IUserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../repos&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MockUserRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IUserRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; users&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getUsers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;users&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Tip&lt;/b&gt;: Adding &quot;async&quot; to a method auto-wraps it in a Promise, making it easy to fake asynchronous activity.&lt;/p&gt;
&lt;p&gt;We can write a test using a testing framework like &lt;strong&gt;Jest&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;controllers/userRepo.spec.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; MockUserRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../repos/mock/mockUserRepo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; userController&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserController&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;mockResponse&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mockReturnValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;json &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mockReturnValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;beforeEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  userController &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MockUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Speedy! And valid since it inherits IUserRepo.&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Should 200 with an empty array of users&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mockResponse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; userController&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;handleGetUsers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;json&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; users&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Congrats. You (more or less) just learned how write testable code!&lt;/strong&gt;. &lt;/p&gt;
&lt;h3 id=&quot;The-primary-wins-of-DI&quot; style=&quot;position:relative;&quot;&gt;The primary wins of DI&lt;a href=&quot;#The-primary-wins-of-DI&quot; aria-label=&quot;The primary wins of DI permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Not only does this decoupling make your code &lt;em&gt;testable&lt;/em&gt;, but it improves the following characteristics of your code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Testability: We can substitute expensive to infrastructure components for mock ones during testing. &lt;/li&gt;
&lt;li&gt;Substitutability: If we program against an interface, we enable a &lt;strong&gt;plugin architecture&lt;/strong&gt; adhering to the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;Liskov Substitution Principle&lt;/a&gt;, which makes it incredibly easy for us to swap out valid plugins, and program against code that doesn&apos;t yet exist. Because the interface defines the &lt;em&gt;shape&lt;/em&gt; of the dependency, all we need to do to substitute the current dependency is create a new one that adheres to the contract defined by the interface. See &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;this article&lt;/a&gt; to dive deeper on that.&lt;/li&gt;
&lt;li&gt;Flexibility: Adhering to the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;Open Closed Principle&lt;/a&gt;, a system should be open for extension but closed for modification. That  means if we want to extend the system, we need only create a new plugin in order to extend the current behavior.&lt;/li&gt;
&lt;li&gt;Delegation: &lt;strong&gt;Inversion of Control&lt;/strong&gt; is the phenomenon we observe when we delegate behavior to be implemented by someone else, but provide the hooks/plugins/callbacks to do so. We design the current component to &lt;em&gt;invert&lt;/em&gt; control to another one. Lots of web frameworks are built on this principle.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Inversion-of-Control--IoC-Containers&quot; style=&quot;position:relative;&quot;&gt;Inversion of Control &amp;#x26; IoC Containers&lt;a href=&quot;#Inversion-of-Control--IoC-Containers&quot; aria-label=&quot;Inversion of Control  IoC Containers permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Applications get much larger than just two components. &lt;/p&gt;
&lt;p&gt;Not only do we need to ensure we&apos;re &lt;strong&gt;referring to interfaces&lt;/strong&gt; and NOT concrete implementations, but we also need to handle the process of manually injecting &lt;em&gt;instances&lt;/em&gt; of dependencies at runtime.&lt;/p&gt;
&lt;p&gt;If your app is relatively small or you&apos;ve got a style guide for hooking up dependencies on your team, you could do this manually.&lt;/p&gt;
&lt;p&gt;If you&apos;ve got a huge app and you don&apos;t have a plan for how you&apos;ll accomplish dependency injection within in your app, it has potential to get out of hand.&lt;/p&gt;
&lt;p&gt;It&apos;s for that reason that &lt;strong&gt;Inversion of Control (IoC) Containers&lt;/strong&gt; exist.&lt;/p&gt;
&lt;p&gt;They work by requiring you to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a container (that will hold all of your app dependencies)&lt;/li&gt;
&lt;li&gt;Make that dependency known to the container (specify that it is &lt;em&gt;injectable&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Resolve the depdendencies that you need by asking the container to inject them&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Some of the more popular ones for JavaScript/TypeScript are &lt;a href=&quot;https://github.com/jeffijoe/awilix&quot;&gt;Awilix&lt;/a&gt; and &lt;a href=&quot;http://inversify.io/&quot;&gt;InversifyJS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Personally, I&apos;m not a huge fan of them and the additional &lt;strong&gt;infrastructure-specific framework logic&lt;/strong&gt; that they scatter all across my codebase. &lt;/p&gt;
&lt;p&gt;If you&apos;re like me and you&apos;re not into &lt;em&gt;container life&lt;/em&gt;, I have &lt;u&gt;my own style guide for injecting dependencies&lt;/u&gt; that I talk about in &lt;a href=&quot;https://solidbook.io&quot;&gt;solidbook.io&lt;/a&gt;. I&apos;m also working on some video content, so stay tuned!&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Inversion of Control&lt;/b&gt;: Traditional control flow for a program is when the program only does what we tell it to do (today). Inversion of control flow happens when we develop frameworks or only refer to &lt;b&gt;plugin architecture&lt;/b&gt; with areas of code that can be hooked into. In these areas, we &lt;i&gt;might not know (today)&lt;/i&gt; how we want it to be used, or we wish to enable developers to add additional functionality. That means that every &lt;b&gt;lifecycle hook in React.js or Angular&lt;/b&gt; is a good example of Inversion of Control in practice. IoC is also often explained by the &quot;Hollywood Design Principle&quot;: &lt;i&gt;Don&apos;t call us, we&apos;ll call you&lt;/i&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Command Query Separation | Object-Oriented Design Principles w/ TypeScript]]></title><description><![CDATA[I recently discovered a programming term, Heisenbug.  No, I'm not talking about about a certain chemistry teacher turned criminal drug-lord…]]></description><link>https://khalilstemmler.com/articles/oop-design-principles/command-query-separation/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/oop-design-principles/command-query-separation/</guid><pubDate>Thu, 29 Aug 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;I recently discovered a programming term, &lt;u&gt;Heisen&lt;em&gt;bug&lt;/em&gt;&lt;/u&gt;. &lt;/p&gt;
&lt;p&gt;No, I&apos;m not talking about about a certain chemistry teacher turned criminal drug-lord. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;HeisenBUG&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;It&apos;s a pun on the name of a certain German physicist, &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Werner_Heisenberg&quot;&gt;Werner Karl &lt;em&gt;Heisenberg&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Heisenberg&apos;s discovery in particle physics was the &lt;u&gt;uncertainty principle&lt;/u&gt;. It stated that &quot;the very act of observing [a particle] alters the position of the particle being observed, making it impossible (in theory) to accurately predict its behavior&quot; &lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Is it just me or does that remind you of your worst debugging nightmares?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;HeisenBUG&lt;/strong&gt; takes after the uncertainty principle, referring to scenarios where it&apos;s incredibly hard to find a bug. It specifically refers to scenarios where the bug seems to disappear or act differently when we make attempts to take a closer look at it.&lt;/p&gt;
&lt;p&gt;In programming, unexpected &lt;strong&gt;side-effects&lt;/strong&gt; are largely the cause of such bugs.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If asking a question &lt;em&gt;changes the answer&lt;/em&gt;, we&apos;re likely to run into problems.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&quot;Command-Query-Separation-CQS&quot; style=&quot;position:relative;&quot;&gt;Command-Query Separation (CQS)&lt;a href=&quot;#Command-Query-Separation-CQS&quot; aria-label=&quot;Command Query Separation CQS permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Command-Query Separation (CQS) is a design principle (while not strictly object-oriented) that states that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a &lt;em&gt;method&lt;/em&gt; is either a &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt; that performs an action OR a &lt;code class=&quot;language-text&quot;&gt;QUERY&lt;/code&gt; that returns data to the caller, but never both.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In simpler terms, &quot;asking a question shouldn&apos;t change the answer&quot;.&lt;/p&gt;
&lt;h3 id=&quot;Why-does-this-matter&quot; style=&quot;position:relative;&quot;&gt;&lt;em&gt;Why does this matter?&lt;/em&gt;&lt;a href=&quot;#Why-does-this-matter&quot; aria-label=&quot;Why does this matter permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The idea is to &lt;strong&gt;separate the code paths&lt;/strong&gt; for operations that &lt;em&gt;change the system&lt;/em&gt; from those that simply &lt;em&gt;request&lt;/em&gt; data from the system.&lt;/p&gt;
&lt;p&gt;By enforcing this separation, the code becomes simpler to understand. &lt;em&gt;Is this changing something, or just fetching something&lt;/em&gt;? When a method does &lt;em&gt;both&lt;/em&gt; (&lt;strong&gt;changes&lt;/strong&gt; the state of the application &lt;em&gt;and&lt;/em&gt; &lt;strong&gt;retrieves&lt;/strong&gt; data), it becomes a lot harder to understand it&apos;s &lt;strong&gt;true purpose&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;This can lead to &lt;u&gt;really hard to reason about&lt;/u&gt; application state.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;A-messy-Job-Recommendations-API-Design&quot; style=&quot;position:relative;&quot;&gt;A messy Job Recommendations API Design&lt;a href=&quot;#A-messy-Job-Recommendations-API-Design&quot; aria-label=&quot;A messy Job Recommendations API Design permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Imagine we were building a &lt;strong&gt;Job Recommendations Service&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Assume we have two API routes:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;GET /jobs         - Returns jobs for me to view
GET /jobs/:jobId  - Returns a particular job&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Consider if everytime I did a &lt;code class=&quot;language-text&quot;&gt;GET&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;/jobs/:jobId&lt;/code&gt;, it &lt;strong&gt;changed the state of the system&lt;/strong&gt; by changing what comes back when I do &lt;code class=&quot;language-text&quot;&gt;GET&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;/jobs&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Eventually, as I view more jobs with &lt;code class=&quot;language-text&quot;&gt;/jobs/:jobId&lt;/code&gt;, I&apos;ll see more relevant jobs in my calls to &lt;code class=&quot;language-text&quot;&gt;/jobs&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In theory, that&apos;s one way to build out job recommendations in our system.&lt;/p&gt;
&lt;p&gt;But this type of design makes the &lt;code class=&quot;language-text&quot;&gt;/jobs&lt;/code&gt; API &lt;em&gt;incredibly inconsistent&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Consider how hard it would be to test and validate it&apos;s working properly.&lt;/p&gt;
&lt;p&gt;Also, consider the actors in this system are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;JobSeekers&lt;/code&gt;: Job seekers are people who are actually looking for jobs&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Recruiters&lt;/code&gt;: Recruiters work for companies and try to get job seekers to apply to jobs&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Employers&lt;/code&gt;: Employers are the people who post the jobs&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Public&lt;/code&gt;: Anonymous users can also view jobs on the job board without an account&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Assume that every actor was able to use the &lt;code class=&quot;language-text&quot;&gt;/jobs/:jobId&lt;/code&gt; API call to retrieve a posting.&lt;/p&gt;
&lt;p&gt;Should the system change for every actor that fetches a job posting with &lt;code class=&quot;language-text&quot;&gt;/jobs/:jobId&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Of course not, &lt;code class=&quot;language-text&quot;&gt;JobSeekers&lt;/code&gt; are probably the only group that this should apply against. &lt;/p&gt;
&lt;p&gt;This &lt;strong&gt;feels really complex&lt;/strong&gt; because several user groups are reliant on the same resource, but we&apos;re trying to apply side-effects for &lt;strong&gt;one of them in particular&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;You can be sure that using a design like this, there would be a dirty &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; statement in there somewhere:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;getJobByJobId.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  userId&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  jobId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; JobId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GetJobByJobIdUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Job&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Job&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; jobId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isJobSeeker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;roles&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; r &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;JobSeeker&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isJobSeeker&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// dirty, log job view&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; job &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;jobRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getJobByJobId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;jobId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;A-better-design&quot; style=&quot;position:relative;&quot;&gt;A better design&lt;a href=&quot;#A-better-design&quot; aria-label=&quot;A better design permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&apos;s be explicit about the &lt;code class=&quot;language-text&quot;&gt;COMMANDS&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;QUERIES&lt;/code&gt;, what changes the system, and what retrieves data.&lt;/p&gt;
&lt;p&gt;We can improve the design by &lt;strong&gt;extracting&lt;/strong&gt; the side-effect into a &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt;-like POST call to &lt;strong&gt;log the job view&lt;/strong&gt; separately from retrieving it.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;GET /jobs                 - Returns all jobs 
GET /jobs/:jobId          - Returns a particular job
POST /jobs/:jobId/view    - 🔥 Logs a job view &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This tremendously simplifies the code paths for both &lt;strong&gt;logging a job view&lt;/strong&gt; and &lt;strong&gt;retrieving a particular job&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;We can improve the design even further by extracting the functionality to see recommended jobs from within it&apos;s own &lt;code class=&quot;language-text&quot;&gt;/jobs/recommendations&lt;/code&gt; API.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;GET /jobs                     - Returns all jobs 
GET /jobs/:jobId              - Returns a particular job
POST /jobs/:jobId/view        - Logs a job view
GET /jobs/recommendations     - 🔥Returns my personal job recommendations 
                                  (used by JobSeekers only)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Usage of this API from the UI would mean that everytime we perform a &lt;code class=&quot;language-text&quot;&gt;GetJobById&lt;/code&gt; &lt;code class=&quot;language-text&quot;&gt;QUERY&lt;/code&gt;, we accompany that with a &lt;code class=&quot;language-text&quot;&gt;LogJobView&lt;/code&gt; &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This way, we have two &lt;strong&gt;separate code paths&lt;/strong&gt;: one for &lt;em&gt;changing the system&lt;/em&gt; and for &lt;em&gt;pulling data out of the system&lt;/em&gt;. We can rest safely knowing that if we change anything with regards to &lt;code class=&quot;language-text&quot;&gt;QUERY&lt;/code&gt;-ing, it won&apos;t break anything in regards to how we execute &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt;s, and vice-versa.&lt;/p&gt;
&lt;h2 id=&quot;Violation-of-the-principle-at-the-code-level&quot; style=&quot;position:relative;&quot;&gt;Violation of the principle at the code level&lt;a href=&quot;#Violation-of-the-principle-at-the-code-level&quot; aria-label=&quot;Violation of the principle at the code level permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Consider you wrote the following &lt;code class=&quot;language-text&quot;&gt;postComment&lt;/code&gt; method in a &lt;strong&gt;Comment Moderation System&lt;/strong&gt;. &lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;commentRepo.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Comment&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  content&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CommentRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;postComment&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; content&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Comment&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; CommentSequelizeModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Comment&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Post comment&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; CommentSequelizeModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; content &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; CommentMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;comment&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// with commentId on it&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;First of all, take a look at method signature:&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;postComment (name: string, url: string, content: string): Promise&amp;lt;Comment&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The name implies that the operation will be a &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt;, but it returns a value as well, violating the principle.&lt;/p&gt;
&lt;p&gt;Perhaps returning the &lt;code class=&quot;language-text&quot;&gt;Comment&lt;/code&gt; created can be justified. Assume a &lt;code class=&quot;language-text&quot;&gt;CommentService&lt;/code&gt; exists, and in order to craft a &lt;a target=&quot;_blank&quot; href=&quot;https://slack.com/intl/en-ca/&quot;&gt;Slack&lt;/a&gt; channel message notifying us of a new comment, we needed the &lt;code class=&quot;language-text&quot;&gt;commentId&lt;/code&gt; of the newly created  &lt;code class=&quot;language-text&quot;&gt;Comment&lt;/code&gt; returned from the &lt;code class=&quot;language-text&quot;&gt;CommentRepo&lt;/code&gt;&apos;s &lt;code class=&quot;language-text&quot;&gt;postComment&lt;/code&gt; method.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;commentService.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CommentService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;postCommentAndPostToSlack&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; content&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;commentRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postComment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; content&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Needs comment.commentId in order to craft the message.&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;slackService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
      New comment posted:
        =&gt; Name: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
        =&gt; Url: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;url&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/commentId/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;comment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
        =&gt; Content: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;content&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So then...&lt;/p&gt;
&lt;h3 id=&quot;Whats-wrong-with-this-code&quot; style=&quot;position:relative;&quot;&gt;What&apos;s wrong with this code?&lt;a href=&quot;#Whats-wrong-with-this-code&quot; aria-label=&quot;Whats wrong with this code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;While the &lt;code class=&quot;language-text&quot;&gt;CommentRepo&lt;/code&gt; method is deceptively named &lt;code class=&quot;language-text&quot;&gt;postComment&lt;/code&gt;, it&apos;s not only responsible for posting the comment, but also for retrieving the comment that was posted. Developers reading the method signature might get confused as to the &lt;strong&gt;single responsibility&lt;/strong&gt; of this method. &lt;code class=&quot;language-text&quot;&gt;QUERY&lt;/code&gt; capability should be delegated to a new method, perhaps &lt;code class=&quot;language-text&quot;&gt;getComment(commentId: string)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;There&apos;s an issue in not generating the id for the &lt;code class=&quot;language-text&quot;&gt;Comment&lt;/code&gt; from within the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;domain layer&lt;/a&gt;, but leaving it up to the persistence layer (Sequelize) as shown here. That can lead to blatant violation of the principle &lt;em&gt;in order to know&lt;/em&gt; the identifier of the &lt;a href=&quot;/articles/typescript-domain-driven-design/entities/&quot;&gt;Entity&lt;/a&gt; just saved to the database. That poor design forces calling code executing a &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt; to not &lt;em&gt;only&lt;/em&gt; know if the &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt; succeeded or failed, but also forces the &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt; to return the value if successful.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Fixing-it&quot; style=&quot;position:relative;&quot;&gt;Fixing it&lt;a href=&quot;#Fixing-it&quot; aria-label=&quot;Fixing it permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In addition to switching to creating the entire &lt;code class=&quot;language-text&quot;&gt;Comment&lt;/code&gt; domain model from within the Domain Layer (using &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;Value Objects&lt;/a&gt; and  &lt;a href=&quot;/articles/typescript-domain-driven-design/entities/&quot;&gt;Entities&lt;/a&gt; containing the &lt;a href=&quot;/articles/auto-increment-or-uuid/&quot;&gt;UUID identifier&lt;/a&gt;), we can segregate the &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt; from the &lt;code class=&quot;language-text&quot;&gt;QUERY&lt;/code&gt; aspect of the &lt;code class=&quot;language-text&quot;&gt;postComment&lt;/code&gt; method by introducing a new method, &lt;code class=&quot;language-text&quot;&gt;getComment&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;commentRepo.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CommentRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;postComment&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;comment&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Comment&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; CommentSequelizeModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Comment&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Post comment&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; CommentSequelizeModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;comment&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getComment&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;commentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CommentId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Promse&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Comment&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; CommentSequelizeModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Comment&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; createQuery &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    createQuery&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;where&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;comment_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; commentId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tostring&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; CommentSequelizeModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; CommentMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;comment&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now, from &lt;code class=&quot;language-text&quot;&gt;CommentService&lt;/code&gt;, we should be able to send the Slack message without relying on the return value from a &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;commentService.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CommentService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;postCommentAndPostToSlack&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; content&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comment&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Comment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Comment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; content&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;commentRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postComment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;comment&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Needs comment.commentId in order to craft the message.&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;slackService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
      New comment posted:
        =&gt; Name: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
        =&gt; Url: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;url&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/commentId/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;comment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
        =&gt; Content: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;content&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Quiz&quot; style=&quot;position:relative;&quot;&gt;Quiz&lt;a href=&quot;#Quiz&quot; aria-label=&quot;Quiz permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&apos;s see how well I explained that.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Which of these are valid &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt;s?&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;getComment (commentId: CommentId): Promise&amp;lt;void&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;createJob (job: Job): Promise&amp;lt;Job&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;postComment (comment: Comment): Promise&amp;lt;Comment[]&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;approveComment (commentId: CommentId): Promise&amp;lt;void&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;flex flex-centered align-center&quot;&gt;
  &lt;button 
    style=&quot;min-width: 165px;&quot;
    onclick=&quot;showQuizAnswer(&apos;quiz-1&apos;)&quot; 
    class=&quot;submit-button purple&quot;&gt;Show answers
  &lt;/button&gt;
  &lt;div 
    id=&quot;quiz-1&quot; 
    style=&quot;margin-left: 0.5rem; display: none;&quot;&gt;Only #4.
  &lt;/div&gt;
&lt;/div&gt;
&lt;br/&gt;
&lt;hr&gt;
&lt;p&gt;Which of these are valid &lt;code class=&quot;language-text&quot;&gt;QUERIES&lt;/code&gt;?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;getAllVinyl (): Promise&amp;lt;Vinyl[]&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;getVinylById (vinylId: VinylId): Promise&amp;lt;Vinyl[]&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;getAllVinyl (): Promise&amp;lt;void&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;getAllVinylById (vinylId: VinylId): Promise&amp;lt;Vinyl&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;flex flex-centered align-center&quot;&gt;
  &lt;button 
    style=&quot;min-width: 165px;&quot;
    onclick=&quot;showQuizAnswer(&apos;quiz-2&apos;)&quot; 
    class=&quot;submit-button purple&quot;&gt;Show answers
  &lt;/button&gt;
  &lt;div 
    id=&quot;quiz-2&quot; 
    style=&quot;margin-left: 0.5rem; display: none;&quot;&gt;#1, #2, and #4, although #2 is confusing to return an array of vinyl in regards to one vinylId.
  &lt;/div&gt;
&lt;/div&gt;
&lt;br/&gt;
&lt;hr&gt;
&lt;h2 id=&quot;CQS-is-a-constantly-occuring-principle-in-several-contexts-of-software-development&quot; style=&quot;position:relative;&quot;&gt;CQS is a constantly occuring principle in several contexts of software development&lt;a href=&quot;#CQS-is-a-constantly-occuring-principle-in-several-contexts-of-software-development&quot; aria-label=&quot;CQS is a constantly occuring principle in several contexts of software development permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;CQS-in-CRUD&quot; style=&quot;position:relative;&quot;&gt;CQS in CRUD&lt;a href=&quot;#CQS-in-CRUD&quot; aria-label=&quot;CQS in CRUD permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;C&lt;/strong&gt;reate &lt;strong&gt;R&lt;/strong&gt;ead &lt;strong&gt;U&lt;/strong&gt;pdate and &lt;strong&gt;D&lt;/strong&gt;elete (CRUD) is often how we think about designing trivial MVC applications. Each operation in CRUD perfectly fits the definition of either a &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt; or a &lt;code class=&quot;language-text&quot;&gt;QUERY&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CRUD Commands: &lt;code class=&quot;language-text&quot;&gt;Create&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Update&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Delete&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;CRUD Queries: &lt;code class=&quot;language-text&quot;&gt;READ&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;CQS-in-RESTful-HTTP&quot; style=&quot;position:relative;&quot;&gt;CQS in RESTful HTTP&lt;a href=&quot;#CQS-in-RESTful-HTTP&quot; aria-label=&quot;CQS in RESTful HTTP permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;CQS also syncs up with the principles of RESTful HTTP. An HTTP method is also either a &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt; or a &lt;code class=&quot;language-text&quot;&gt;QUERY&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP Commands: &lt;code class=&quot;language-text&quot;&gt;POST&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;PUT&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;DELETE&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;PATCH&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;HTTP Queries: &lt;code class=&quot;language-text&quot;&gt;GET&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In times where it may be challenging to think about the behaviour of a particular RESTful API route, think back to the CQS principle.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create User: POST - &lt;code class=&quot;language-text&quot;&gt;/api/users/new&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Get a user: GET - &lt;code class=&quot;language-text&quot;&gt;/api/users/:userId&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;CQS-in-SQL&quot; style=&quot;position:relative;&quot;&gt;CQS in SQL&lt;a href=&quot;#CQS-in-SQL&quot; aria-label=&quot;CQS in SQL permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Nearly every operation we do in SQL is a &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt; and only one operation is a &lt;code class=&quot;language-text&quot;&gt;QUERY&lt;/code&gt;. I&apos;m sure you can guess which one (hint: it rhymes with &quot;REFLECT&quot;).&lt;/p&gt;
&lt;h3 id=&quot;CQS-in-Use-Case-Design&quot; style=&quot;position:relative;&quot;&gt;CQS in Use-Case Design&lt;a href=&quot;#CQS-in-Use-Case-Design&quot; aria-label=&quot;CQS in Use Case Design permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;Projects beyond simple MVC&lt;/a&gt; are centered around the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt; of the application. These are the &lt;strong&gt;features&lt;/strong&gt; for an individual &lt;strong&gt;group&lt;/strong&gt; of people/&lt;code class=&quot;language-text&quot;&gt;Actors&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Every use case is &lt;em&gt;strictly&lt;/em&gt; a command or a query.&lt;/p&gt;
&lt;p&gt;In a &lt;code class=&quot;language-text&quot;&gt;Blog&lt;/code&gt; subdomain,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Commands: &lt;code class=&quot;language-text&quot;&gt;CreatePost&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;UpdatePost&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;DeletePost&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;PostComment&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;UpdateComment&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Queries: &lt;code class=&quot;language-text&quot;&gt;GetPostById&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;GetAllPosts&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;GetCommentById&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;GetAllCommentsForPost&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;CQS-in-Domain-Driven-Design-Architecture-with-CQRS&quot; style=&quot;position:relative;&quot;&gt;CQS in Domain-Driven Design Architecture with CQRS&lt;a href=&quot;#CQS-in-Domain-Driven-Design-Architecture-with-CQRS&quot; aria-label=&quot;CQS in Domain Driven Design Architecture with CQRS permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In Domain-Driven Design, it makes sense to separate the &lt;code class=&quot;language-text&quot;&gt;READ&lt;/code&gt; models from the &lt;code class=&quot;language-text&quot;&gt;WRITE&lt;/code&gt; models. &lt;code class=&quot;language-text&quot;&gt;WRITE&lt;/code&gt;s usually take a little bit more time to finish executing because a &lt;code class=&quot;language-text&quot;&gt;WRITE&lt;/code&gt; to &lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;an aggregate&lt;/a&gt; requires the aggregate to be fully-constituted and contain everything within it&apos;s consistency boundary in order to enforce &lt;a href=&quot;/wiki/invariant/&quot;&gt;invariants&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Using the same &lt;code class=&quot;language-text&quot;&gt;READ&lt;/code&gt; model as a &lt;code class=&quot;language-text&quot;&gt;WRITE&lt;/code&gt; model can be &lt;strong&gt;expensive&lt;/strong&gt; as we&apos;ve explored in &lt;a href=&quot;/articles/typescript-domain-driven-design/one-to-many-performance/&quot;&gt;this article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It makes more sense to enable the &lt;code class=&quot;language-text&quot;&gt;READ&lt;/code&gt; models to be used for all &lt;code class=&quot;language-text&quot;&gt;QUERIES&lt;/code&gt; and the &lt;code class=&quot;language-text&quot;&gt;WRITE&lt;/code&gt; model to be used for the &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;This separation into &lt;strong&gt;two different types of models&lt;/strong&gt; is an architectural pattern called &lt;strong&gt;Command Query &lt;em&gt;Responsibility&lt;/em&gt; Separation&lt;/strong&gt; (CQRS).&lt;/p&gt;
&lt;p&gt;If you&apos;re doing &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design&lt;/a&gt;, it will likely be hard for you to avoid it.&lt;/p&gt;
&lt;h3 id=&quot;Performing-Reads-in-CQRS&quot; style=&quot;position:relative;&quot;&gt;Performing Reads in CQRS&lt;a href=&quot;#Performing-Reads-in-CQRS&quot; aria-label=&quot;Performing Reads in CQRS permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/design-principles/cqrs-reads.svg&quot; alt=&quot;Command Query Responsibility Separation | Reads&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Performing-Writes-in-CQRS&quot; style=&quot;position:relative;&quot;&gt;Performing Writes in CQRS&lt;a href=&quot;#Performing-Writes-in-CQRS&quot; aria-label=&quot;Performing Writes in CQRS permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/design-principles/cqrs-writes.svg&quot; alt=&quot;Command Query Responsibility Separation | Writes&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;Summary&quot; style=&quot;position:relative;&quot;&gt;Summary&lt;a href=&quot;#Summary&quot; aria-label=&quot;Summary permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;In theory, the vast majority of operations that we write in programming only either do one or the other (change the application state, or retrieve some data), but there  are times where it can be unclear.&lt;/li&gt;
&lt;li&gt;Being conscious of this principle can clear up any ambiguity towards if a method of a &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt; or a &lt;code class=&quot;language-text&quot;&gt;QUERY&lt;/code&gt; and if we expect any side effects to change the state of the app. This reduces bugs, improves readability, and makes code more testable.&lt;/li&gt;
&lt;li&gt;CQS usually isn&apos;t thought about in simple CRUD applications because each of the operations in &lt;strong&gt;C&lt;/strong&gt;reate &lt;strong&gt;R&lt;/strong&gt;ead &lt;strong&gt;U&lt;/strong&gt;pdate and &lt;strong&gt;D&lt;/strong&gt;elete operations are obviously either a command or a query.&lt;/li&gt;
&lt;li&gt;CQS is well-suited towards complex domains where Domain-Driven Design is most useful.&lt;/li&gt;
&lt;li&gt;There exists another technique called CQRS which is essentially CQS, but at the architectural level. &lt;/li&gt;
&lt;li&gt;In DDD apps, use cases can sometimes ambiguously feel like a &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt; and a &lt;code class=&quot;language-text&quot;&gt;QUERY&lt;/code&gt;, like the &lt;code class=&quot;language-text&quot;&gt;GetJobById&lt;/code&gt; &lt;code class=&quot;language-text&quot;&gt;QUERY&lt;/code&gt; (&lt;em&gt;Job board example&lt;/em&gt;). It&apos;s important, for performance, to be aware of what really is a &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt; and what really is a &lt;code class=&quot;language-text&quot;&gt;QUERY&lt;/code&gt;, and use CQRS to separate the read and write models.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Uncertainty_principle&quot;&gt;Uncertainty Principle&lt;/a&gt; - Fascinating wikipedia entry on the principle also sometimes known as &lt;em&gt;The Heisenberg Effect&lt;/em&gt;.&lt;/p&gt;
&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[How to Setup a TypeScript + Node.js Project]]></title><description><![CDATA[We talk about a lot of advanced Node.js and TypeScript concepts on this blog, particularly Domain-Driven Design and large-scale enterprise…]]></description><link>https://khalilstemmler.com/blogs/typescript/node-starter-project/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/typescript/node-starter-project/</guid><pubDate>Thu, 29 Aug 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;We talk about a lot of &lt;strong&gt;advanced Node.js and TypeScript&lt;/strong&gt; concepts on this blog, particularly Domain-Driven Design and large-scale enterprise application patterns. However, after receiving emails from readers interested in seeing what a basic TypeScript starter project looks like, I&apos;ve put together just that.&lt;/p&gt;
&lt;h3 id=&quot;Prequisites&quot; style=&quot;position:relative;&quot;&gt;Prequisites&lt;a href=&quot;#Prequisites&quot; aria-label=&quot;Prequisites permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You should have Node and npm installed&lt;/li&gt;
&lt;li&gt;You should be familiar with Node and the npm ecosystem&lt;/li&gt;
&lt;li&gt;You have a code editor installed (preferably VS Code, it&apos;s the champ for TypeScript)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Goals&quot; style=&quot;position:relative;&quot;&gt;Goals&lt;a href=&quot;#Goals&quot; aria-label=&quot;Goals permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In this short guide, I&apos;ll walk you through the process of creating a basic TypeScript application and compiling it. It&apos;s actually &lt;em&gt;really&lt;/em&gt; easy!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/stemmlerjs/simple-typescript-starter&quot;&gt;View the source&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Afterwards, we&apos;ll setup a few scripts for hot-reloading in &lt;code class=&quot;language-text&quot;&gt;development&lt;/code&gt;, building for &lt;code class=&quot;language-text&quot;&gt;production&lt;/code&gt;, and running in &lt;code class=&quot;language-text&quot;&gt;production&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;About-TypeScript&quot; style=&quot;position:relative;&quot;&gt;About TypeScript&lt;a href=&quot;#About-TypeScript&quot; aria-label=&quot;About TypeScript permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;TypeScript, developed and appropriated labeled by Microsoft as &quot;JavaScript that scales&quot;, is a superset of JavaScript, meaning that everything JavaScript can do, TypeScript can do (&lt;del&gt;and more&lt;/del&gt; better).&lt;/p&gt;
&lt;p&gt;TypeScript was primarily meant to solve two problems:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Provide JavaScript developers with an &lt;em&gt;optional type system&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Provide JavaScript developers with the ability to utilize &lt;strong&gt;planned features from future JavaScript editions&lt;/strong&gt; against &lt;em&gt;current JavaScript engines&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We use TypeScript for most of the topics on this blog because it&apos;s a lot better suited for creating long-lasting software and having the compiler help catch bugs and validate types is tremendously helpful.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;Initial-Setup&quot; style=&quot;position:relative;&quot;&gt;Initial Setup&lt;a href=&quot;#Initial-Setup&quot; aria-label=&quot;Initial Setup permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&apos;s create a folder for us to work in. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; typescript-starter
&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; typescript-starter&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, we&apos;ll setup the project &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt; and add the dependencies.&lt;/p&gt;
&lt;h3 id=&quot;Setup-Nodejs-packagejson&quot; style=&quot;position:relative;&quot;&gt;Setup Node.js package.json&lt;a href=&quot;#Setup-Nodejs-packagejson&quot; aria-label=&quot;Setup Nodejs packagejson permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Using the &lt;code class=&quot;language-text&quot;&gt;-y&lt;/code&gt; flag when creating a &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt; will simply approve all the defaults.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; init -y&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Add-TypeScript-as-a-dev-dependency&quot; style=&quot;position:relative;&quot;&gt;Add TypeScript as a dev dependency&lt;a href=&quot;#Add-TypeScript-as-a-dev-dependency&quot; aria-label=&quot;Add TypeScript as a dev dependency permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This probably doesn&apos;t come as a surprise ;)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; typescript --save-dev&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After we install &lt;code class=&quot;language-text&quot;&gt;typescript&lt;/code&gt;, we get access to the command line TypeScript compiler through the &lt;code class=&quot;language-text&quot;&gt;tsc&lt;/code&gt; command. More on that below.&lt;/p&gt;
&lt;h3 id=&quot;Install-ambient-Nodejs-types-for-TypeScript&quot; style=&quot;position:relative;&quot;&gt;Install ambient Node.js types for TypeScript&lt;a href=&quot;#Install-ambient-Nodejs-types-for-TypeScript&quot; aria-label=&quot;Install ambient Nodejs types for TypeScript permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;TypeScript has Implicit, Explicit, and &lt;em&gt;Ambient&lt;/em&gt; types. Ambient types are types that get added to the global execution scope. Since we&apos;re using Node, it would be good if we could get type safety and auto-completion on the Node apis like &lt;code class=&quot;language-text&quot;&gt;file&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;path&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;process&lt;/code&gt;, etc. That&apos;s what installing the &lt;a href=&quot;https://github.com/DefinitelyTyped/DefinitelyTyped&quot;&gt;DefinitelyTyped&lt;/a&gt; type definition for Node will do.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; @types/node --save-dev&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Create-a-tsconfigjson&quot; style=&quot;position:relative;&quot;&gt;Create a &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt;.&lt;a href=&quot;#Create-a-tsconfigjson&quot; aria-label=&quot;Create a tsconfigjson permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt; is where we define the TypeScript compiler options. We can create a tsconfig with several options set.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;npx tsc --init --rootDir src --outDir build &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
--esModuleInterop --resolveJsonModule --lib es6 &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
--module commonjs --allowJs &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; --noImplicitAny &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;rootDir&lt;/code&gt;: This is where TypeScript looks for our code. We&apos;ve configured it to look in the &lt;code class=&quot;language-text&quot;&gt;src/&lt;/code&gt; folder. That&apos;s where we&apos;ll write our TypeScript.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;outDir&lt;/code&gt;: Where TypeScript puts our compiled code. We want it to go to a &lt;code class=&quot;language-text&quot;&gt;build/&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;esModuleInterop&lt;/code&gt;: If you were in the JavaScript space over the past couple of years, you might have recognized that modules systems had gotten a little bit out of control (AMD, SystemJS, ES Modules, etc). For a topic that requires a much longer discussion, if we&apos;re using &lt;code class=&quot;language-text&quot;&gt;commonjs&lt;/code&gt; as our module system (for Node apps, you should be), then we need this to be set to &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;resolveJsonModule&lt;/code&gt;: If we use JSON in this project, this option allows TypeScript to use it.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;lib&lt;/code&gt;: This option adds &lt;em&gt;ambient&lt;/em&gt; types to our project, allowing us to rely on features from different Ecmascript versions, testing libraries, and even the browser DOM api. We&apos;d like to utilize some &lt;code class=&quot;language-text&quot;&gt;es6&lt;/code&gt; language features. This all gets compiled down to &lt;code class=&quot;language-text&quot;&gt;es5&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;module&lt;/code&gt;: &lt;code class=&quot;language-text&quot;&gt;commonjs&lt;/code&gt; is the standard Node module system in 2019. Let&apos;s use that.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;allowJs&lt;/code&gt;: If you&apos;re converting an old JavaScript project to TypeScript, this option will  allow you to include &lt;code class=&quot;language-text&quot;&gt;.js&lt;/code&gt; files among &lt;code class=&quot;language-text&quot;&gt;.ts&lt;/code&gt; ones.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;noImplicitAny&lt;/code&gt;: In TypeScript files, don&apos;t allow a type to be unexplicitly specified. Every type needs to either have a specific type or be explicitly declared &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;. No implicit &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;s.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At this point, you should have a &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt; that looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;/* Basic Options */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;incremental&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                   &lt;span class=&quot;token comment&quot;&gt;/* Enable incremental compilation */&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;target&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;es5&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                          &lt;span class=&quot;token comment&quot;&gt;/* Specify ECMAScript target version: &apos;ES3&apos; (default), &apos;ES5&apos;, &apos;ES2015&apos;, &apos;ES2016&apos;, &apos;ES2017&apos;, &apos;ES2018&apos;, &apos;ES2019&apos; or &apos;ESNEXT&apos;. */&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;module&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;commonjs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                     &lt;span class=&quot;token comment&quot;&gt;/* Specify module code generation: &apos;none&apos;, &apos;commonjs&apos;, &apos;amd&apos;, &apos;system&apos;, &apos;umd&apos;, &apos;es2015&apos;, or &apos;ESNext&apos;. */&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;lib&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;es6&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                     &lt;span class=&quot;token comment&quot;&gt;/* Specify library files to be included in the compilation. */&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;allowJs&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                          &lt;span class=&quot;token comment&quot;&gt;/* Allow javascript files to be compiled. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;checkJs&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                       &lt;span class=&quot;token comment&quot;&gt;/* Report errors in .js files. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;jsx&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;preserve&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                     &lt;span class=&quot;token comment&quot;&gt;/* Specify JSX code generation: &apos;preserve&apos;, &apos;react-native&apos;, or &apos;react&apos;. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;declaration&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                   &lt;span class=&quot;token comment&quot;&gt;/* Generates corresponding &apos;.d.ts&apos; file. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;declarationMap&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;/* Generates a sourcemap for each corresponding &apos;.d.ts&apos; file. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;sourceMap&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                     &lt;span class=&quot;token comment&quot;&gt;/* Generates corresponding &apos;.map&apos; file. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;outFile&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                       &lt;span class=&quot;token comment&quot;&gt;/* Concatenate and emit output to single file. */&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;outDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;build&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                          &lt;span class=&quot;token comment&quot;&gt;/* Redirect output structure to the directory. */&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;rootDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                         &lt;span class=&quot;token comment&quot;&gt;/* Specify the root directory of input files. Use to control the output directory structure with --outDir. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;composite&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                     &lt;span class=&quot;token comment&quot;&gt;/* Enable project compilation */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;tsBuildInfoFile&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;               &lt;span class=&quot;token comment&quot;&gt;/* Specify file to store incremental compilation information */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;removeComments&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;/* Do not emit comments to output. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;noEmit&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                        &lt;span class=&quot;token comment&quot;&gt;/* Do not emit outputs. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;importHelpers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                 &lt;span class=&quot;token comment&quot;&gt;/* Import emit helpers from &apos;tslib&apos;. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;downlevelIteration&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;            &lt;span class=&quot;token comment&quot;&gt;/* Provide full support for iterables in &apos;for-of&apos;, spread, and destructuring when targeting &apos;ES5&apos; or &apos;ES3&apos;. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;isolatedModules&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;               &lt;span class=&quot;token comment&quot;&gt;/* Transpile each file as a separate module (similar to &apos;ts.transpileModule&apos;). */&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/* Strict Type-Checking Options */&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;strict&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                           &lt;span class=&quot;token comment&quot;&gt;/* Enable all strict type-checking options. */&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;noImplicitAny&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                    &lt;span class=&quot;token comment&quot;&gt;/* Raise error on expressions and declarations with an implied &apos;any&apos; type. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;strictNullChecks&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;              &lt;span class=&quot;token comment&quot;&gt;/* Enable strict null checks. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;strictFunctionTypes&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;           &lt;span class=&quot;token comment&quot;&gt;/* Enable strict checking of function types. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;strictBindCallApply&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;           &lt;span class=&quot;token comment&quot;&gt;/* Enable strict &apos;bind&apos;, &apos;call&apos;, and &apos;apply&apos; methods on functions. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;strictPropertyInitialization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;/* Enable strict checking of property initialization in classes. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;noImplicitThis&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;/* Raise error on &apos;this&apos; expressions with an implied &apos;any&apos; type. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;alwaysStrict&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                  &lt;span class=&quot;token comment&quot;&gt;/* Parse in strict mode and emit &lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt; for each source file. */

    &lt;span class=&quot;token comment&quot;&gt;/* Additional Checks */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;noUnusedLocals&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;/* Report errors on unused locals. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;noUnusedParameters&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;            &lt;span class=&quot;token comment&quot;&gt;/* Report errors on unused parameters. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;noImplicitReturns&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;             &lt;span class=&quot;token comment&quot;&gt;/* Report error when not all code paths in function return a value. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;noFallthroughCasesInSwitch&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;/* Report errors for fallthrough cases in switch statement. */&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/* Module Resolution Options */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;moduleResolution&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;            &lt;span class=&quot;token comment&quot;&gt;/* Specify module resolution strategy: &apos;node&apos; (Node.js) or &apos;classic&apos; (TypeScript pre-1.6). */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;baseUrl&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                       &lt;span class=&quot;token comment&quot;&gt;/* Base directory to resolve non-absolute module names. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;paths&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                           &lt;span class=&quot;token comment&quot;&gt;/* A series of entries which re-map imports to lookup locations relative to the &apos;baseUrl&apos;. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;rootDirs&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                        &lt;span class=&quot;token comment&quot;&gt;/* List of root folders whose combined content represents the structure of the project at runtime. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;typeRoots&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                       &lt;span class=&quot;token comment&quot;&gt;/* List of folders to include type definitions from. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;types&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                           &lt;span class=&quot;token comment&quot;&gt;/* Type declaration files to be included in compilation. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;allowSyntheticDefaultImports&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;/* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;esModuleInterop&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                  &lt;span class=&quot;token comment&quot;&gt;/* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies &apos;allowSyntheticDefaultImports&apos;. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;preserveSymlinks&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;              &lt;span class=&quot;token comment&quot;&gt;/* Do not resolve the real path of symlinks. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;allowUmdGlobalAccess&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;          &lt;span class=&quot;token comment&quot;&gt;/* Allow accessing UMD globals from modules. */&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/* Source Map Options */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;sourceRoot&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                      &lt;span class=&quot;token comment&quot;&gt;/* Specify the location where debugger should locate TypeScript files instead of source locations. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;mapRoot&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                         &lt;span class=&quot;token comment&quot;&gt;/* Specify the location where debugger should locate map files instead of generated locations. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;inlineSourceMap&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;               &lt;span class=&quot;token comment&quot;&gt;/* Emit a single file with source maps instead of having a separate file. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;inlineSources&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                 &lt;span class=&quot;token comment&quot;&gt;/* Emit the source alongside the sourcemaps within a single file; requires &apos;--inlineSourceMap&apos; or &apos;--sourceMap&apos; to be set. */&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/* Experimental Options */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;experimentalDecorators&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;/* Enables experimental support for ES7 decorators. */&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;emitDecoratorMetadata&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;         &lt;span class=&quot;token comment&quot;&gt;/* Enables experimental support for emitting type metadata for decorators. */&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/* Advanced Options */&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;resolveJsonModule&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;                 &lt;span class=&quot;token comment&quot;&gt;/* Include modules imported with &apos;.json&apos; extension */&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can go ahead and clean the commented out stuff that we don&apos;t need. Our &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt; should look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;target&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;es5&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                          
    &lt;span class=&quot;token property&quot;&gt;&quot;module&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;commonjs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                    
    &lt;span class=&quot;token property&quot;&gt;&quot;lib&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;es6&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                     
    &lt;span class=&quot;token property&quot;&gt;&quot;allowJs&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;outDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;build&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                          
    &lt;span class=&quot;token property&quot;&gt;&quot;rootDir&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;strict&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;         
    &lt;span class=&quot;token property&quot;&gt;&quot;noImplicitAny&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;esModuleInterop&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;resolveJsonModule&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We&apos;re set to run our first TypeScript file.&lt;/p&gt;
&lt;h3 id=&quot;Create-the-src-folder-and-create-our-first-TypeScript-file&quot; style=&quot;position:relative;&quot;&gt;Create the &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; folder and create our first TypeScript file&lt;a href=&quot;#Create-the-src-folder-and-create-our-first-TypeScript-file&quot; aria-label=&quot;Create the src folder and create our first TypeScript file permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; src
&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; src/index.ts&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And let&apos;s write some code.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Hello world!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Compiling-our-TypeScript&quot; style=&quot;position:relative;&quot;&gt;Compiling our TypeScript&lt;a href=&quot;#Compiling-our-TypeScript&quot; aria-label=&quot;Compiling our TypeScript permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To compile our code, we&apos;ll need to run the &lt;code class=&quot;language-text&quot;&gt;tsc&lt;/code&gt; command using &lt;code class=&quot;language-text&quot;&gt;npx&lt;/code&gt;, the Node package executer. &lt;code class=&quot;language-text&quot;&gt;tsc&lt;/code&gt; will read the &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt; in the current directory, and apply  the configuration against the TypeScript compiler to generate the compiled JavaScript code.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;npx tsc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Our-compiled-code&quot; style=&quot;position:relative;&quot;&gt;Our compiled code&lt;a href=&quot;#Our-compiled-code&quot; aria-label=&quot;Our compiled code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Check out &lt;code class=&quot;language-text&quot;&gt;build/index.js&lt;/code&gt;, we&apos;ve compiled our first TypeScript file.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Hello world!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;h2 id=&quot;Useful-configurations--scripts&quot; style=&quot;position:relative;&quot;&gt;Useful configurations &amp;#x26; scripts&lt;a href=&quot;#Useful-configurations--scripts&quot; aria-label=&quot;Useful configurations  scripts permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Cold-reloading&quot; style=&quot;position:relative;&quot;&gt;Cold reloading&lt;a href=&quot;#Cold-reloading&quot; aria-label=&quot;Cold reloading permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Cold reloading is nice for local development. In order to do this, we&apos;ll need to rely on a couple more packages: &lt;code class=&quot;language-text&quot;&gt;ts-node&lt;/code&gt; for running TypeScript code directly without having to wait for it be compiled, and &lt;code class=&quot;language-text&quot;&gt;nodemon&lt;/code&gt;, to watch for changes to our code and automatically restart when a file is changed.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save-dev ts-node nodemon&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Add a &lt;code class=&quot;language-text&quot;&gt;nodemon.json&lt;/code&gt; config.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;watch&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;ext&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.ts,.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;ignore&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;exec&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;npx ts-node ./src/index.ts&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then to run the project, all we have to do is run &lt;code class=&quot;language-text&quot;&gt;nodemon&lt;/code&gt;. Let&apos;s add a script for that.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;start:dev&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;npx nodemon&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By running &lt;code class=&quot;language-text&quot;&gt;npm run start:dev&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;npx nodemon&lt;/code&gt; will start our app using &lt;code class=&quot;language-text&quot;&gt;npx ts-node ./src/index.ts&lt;/code&gt;, watching for changes to &lt;code class=&quot;language-text&quot;&gt;.ts&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;.js&lt;/code&gt; files from within &lt;code class=&quot;language-text&quot;&gt;/src&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Creating-production-builds&quot; style=&quot;position:relative;&quot;&gt;Creating production builds&lt;a href=&quot;#Creating-production-builds&quot; aria-label=&quot;Creating production builds permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In order to &lt;em&gt;clean&lt;/em&gt; and compile the project for production, we can add a &lt;code class=&quot;language-text&quot;&gt;build&lt;/code&gt; script.&lt;/p&gt;
&lt;p&gt;Install &lt;code class=&quot;language-text&quot;&gt;rimraf&lt;/code&gt;, a cross-platform tool that acts like the &lt;code class=&quot;language-text&quot;&gt;rm -rf&lt;/code&gt; command (just obliterates whatever you tell it to).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save-dev rimraf&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then, add this to your &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;build&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;rimraf ./build &amp;amp;&amp;amp; tsc&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, when we run &lt;code class=&quot;language-text&quot;&gt;npm run build&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;rimraf&lt;/code&gt; will remove our old &lt;code class=&quot;language-text&quot;&gt;build&lt;/code&gt; folder before the TypeScript compiler emits new code to &lt;code class=&quot;language-text&quot;&gt;dist&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Production-startup-script&quot; style=&quot;position:relative;&quot;&gt;Production startup script&lt;a href=&quot;#Production-startup-script&quot; aria-label=&quot;Production startup script permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In order to start the app in production, all we need to do is run the &lt;code class=&quot;language-text&quot;&gt;build&lt;/code&gt; command first, and then execute the compiled JavaScript at &lt;code class=&quot;language-text&quot;&gt;build/index.js&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The startup script looks like this.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;start&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;npm run build &amp;amp;&amp;amp; node build/index.js&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I told you it was simple! Now, off you go. &lt;strong&gt;Create great things, my friend&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;View-the-source&quot; style=&quot;position:relative;&quot;&gt;View the source&lt;a href=&quot;#View-the-source&quot; aria-label=&quot;View the source permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A reminder that you can view &lt;a href=&quot;https://github.com/stemmlerjs/simple-typescript-starter&quot;&gt;the entire source code&lt;/a&gt; for this here.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;Scripts-overview&quot; style=&quot;position:relative;&quot;&gt;Scripts overview&lt;a href=&quot;#Scripts-overview&quot; aria-label=&quot;Scripts overview permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;npm-run-startdev&quot; style=&quot;position:relative;&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;npm run start:dev&lt;/code&gt;&lt;a href=&quot;#npm-run-startdev&quot; aria-label=&quot;npm run startdev permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Starts the application in development using &lt;code class=&quot;language-text&quot;&gt;nodemon&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;ts-node&lt;/code&gt; to do cold reloading.&lt;/p&gt;
&lt;h3 id=&quot;npm-run-build&quot; style=&quot;position:relative;&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;npm run build&lt;/code&gt;&lt;a href=&quot;#npm-run-build&quot; aria-label=&quot;npm run build permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Builds the app at &lt;code class=&quot;language-text&quot;&gt;build&lt;/code&gt;, cleaning the folder first.&lt;/p&gt;
&lt;h3 id=&quot;npm-run-start&quot; style=&quot;position:relative;&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;npm run start&lt;/code&gt;&lt;a href=&quot;#npm-run-start&quot; aria-label=&quot;npm run start permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Starts the app in production by first building the project with &lt;code class=&quot;language-text&quot;&gt;npm run build&lt;/code&gt;, and then executing the compiled JavaScript at &lt;code class=&quot;language-text&quot;&gt;build/index.js&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Testing-Added-November-26th-2022&quot; style=&quot;position:relative;&quot;&gt;Testing (Added November 26th, 2022)&lt;a href=&quot;#Testing-Added-November-26th-2022&quot; aria-label=&quot;Testing Added November 26th 2022 permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I want to talk to you about testing for a moment. I&apos;ve made a few additions to the project for the purposes of getting my mentorship students up and running faster.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There are two ways to write tests in this project.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stateless testing&lt;/strong&gt;: You can write your tests &lt;a href=&quot;https://github.com/stemmlerjs/simple-typescript-starter/blob/master/src/index.spec.ts&quot;&gt;like this&lt;/a&gt;, similarly to how most testing documentation will tell you to write them. This is the simplest way, and it works well for basic unit tests against &lt;em&gt;stateless&lt;/em&gt; functions or components.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;/wiki/testing/stateful-tests&quot;&gt;Stateful Testing&lt;/a&gt; (Given-When-Then style)&lt;/strong&gt;: This is how I write my &lt;em&gt;High-Value Tests (HVTs)&lt;/em&gt; (also known as Acceptance Tests). You can use the Given-When-Then Gherkins format enabled by &lt;code class=&quot;language-text&quot;&gt;jest-cucumber&lt;/code&gt;. I&apos;ve provided a basic example which you can find within the &lt;code class=&quot;language-text&quot;&gt;useCase&lt;/code&gt; folder &lt;a href=&quot;https://github.com/stemmlerjs/simple-typescript-starter/tree/master/src/useCase&quot;&gt;here&lt;/a&gt;. For a &lt;a href=&quot;https://github.com/stemmlerjs/how-to-test-code-reliant-on-apis/tree/main/after/src/modules/users/useCases/createUser&quot;&gt;real-world example of this, check out this folder&lt;/a&gt; and &lt;a href=&quot;https://khalilstemmler.com/articles/test-driven-development/how-to-test-code-coupled-to-apis-or-databases/&quot;&gt;read this article&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This is my &lt;em&gt;preferred approach&lt;/em&gt; most of the time. Especially for stateful tests.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;(Recommendation)&lt;/strong&gt;: Use the stateless testing approach when you&apos;re testing stateless functions or domain objects like &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-value-object/&quot;&gt;value objects&lt;/a&gt; and &lt;a href=&quot;https://khalilstemmler.com/articles/typescript-domain-driven-design/entities/&quot;&gt;entities&lt;/a&gt;.
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Linting&quot; style=&quot;position:relative;&quot;&gt;Linting&lt;a href=&quot;#Linting&quot; aria-label=&quot;Linting permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Oh yeah, linting is another thing you&apos;ll most likely want to do. If you&apos;re interested in that, read the next post, &quot;&lt;a href=&quot;/blogs/typescript/eslint-for-typescript/&quot;&gt;How to use ESLint with TypeScript&lt;/a&gt;&quot;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[What's Unscalable about JavaScript? | TypeScript OOP]]></title><description><![CDATA[Microsoft called TypeScript JavaScript that scales... what's so unscalable about JavaScript? With respect to software development, there are…]]></description><link>https://khalilstemmler.com/blogs/typescript/why-is-javascript-unscalable/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/typescript/why-is-javascript-unscalable/</guid><pubDate>Wed, 21 Aug 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Microsoft called TypeScript &lt;em&gt;JavaScript that scales&lt;/em&gt;... what&apos;s so &lt;em&gt;unscalable&lt;/em&gt; about JavaScript?&lt;/p&gt;
&lt;p&gt;With respect to software development, there are &lt;strong&gt;two ways&lt;/strong&gt; to think about scalability.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Performance scalability&lt;/li&gt;
&lt;li&gt;Productivity scalability&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;TypeScript is meant to address &lt;strong&gt;2. Productivity scalability&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;Like most dynamically-typed languages, the &lt;u&gt;lack of types&lt;/u&gt; in JavaScript can drastically improve &lt;strong&gt;initial productivity levels&lt;/strong&gt; on certain projects, but there are factors that exist in other projects (team size, code size, intended code lifespan, domain complexity), in which the lack of types can be detrimental to &lt;strong&gt;code quality&lt;/strong&gt; and &lt;strong&gt;understandability&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;It&apos;s been agreed upon that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It&apos;s better enable the compiler to catch silly bugs, typos, and other errors at compile time, rather than in production at runtime.&lt;/li&gt;
&lt;li&gt;Tests are the best documentation possible for your code. Types are no substitute for writing tests, but they can do a good job at reducing the surface area of bugs. &lt;/li&gt;
&lt;li&gt;Tests also enable faster and safer refactoring. Similarly, if no tests exist, types can (at the very least) catch syntatic inaccuracies.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We&apos;ve talked about it previously, but TypeScript addresses #3 of the &lt;a href=&quot;/wiki/3-categories-of-hard-software-problems/&quot;&gt;Hard Software Problems&lt;/a&gt;: The Compled Domain Problem.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;See also&lt;/b&gt;: &quot;&lt;a href=&quot;/articles/when-to-use-typescript-guide/&quot;&gt;When to Use TypeScript&lt;/a&gt;&quot;, a Detailed Guide through Common Scenarios.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Functional Error Handling with Express.js and DDD | Enterprise Node.js + TypeScript]]></title><description><![CDATA[Imagine a world where you could open a severely rattled bottle of Pepsi with brazen confidence, not hesitating to consider the possibility…]]></description><link>https://khalilstemmler.com/articles/enterprise-typescript-nodejs/functional-error-handling/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/enterprise-typescript-nodejs/functional-error-handling/</guid><pubDate>Wed, 14 Aug 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Imagine a world where you could open a &lt;em&gt;severely rattled&lt;/em&gt; bottle of Pepsi with &lt;strong&gt;brazen confidence&lt;/strong&gt;, not hesitating to consider the possibility that it might end up drenching you.&lt;/p&gt;
&lt;p&gt;Imagine a world where nothing ever went wrong; where you &lt;u&gt;only ever had to consider the &lt;strong&gt;happy path&lt;/strong&gt;&lt;/u&gt;. &lt;/p&gt;
&lt;p&gt;Let me know when we discover that world, because it&apos;s certainly &lt;u&gt;not the one we currently live in&lt;/u&gt;. And it&apos;s something that&apos;s &lt;em&gt;especially&lt;/em&gt; true with programming. &lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;Errors-need-love-too-️&quot; style=&quot;position:relative;&quot;&gt;Errors need love too ❤️&lt;a href=&quot;#Errors-need-love-too-%EF%B8%8F&quot; aria-label=&quot;Errors need love too ️ permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In most programming projects, there&apos;s confusion as to &lt;strong&gt;how and where&lt;/strong&gt; errors should be handled.&lt;/p&gt;
&lt;p&gt;They account of a large portion of our application&apos;s &lt;strong&gt;possible states&lt;/strong&gt;, and more often than not, it&apos;s one of the &lt;em&gt;last&lt;/em&gt; things considered. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Do I &lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt; an error and let the client figure out how to handle it?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Do I return &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;?&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When we &lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt; errors, we disrupt the flow of the program and make it trickier for someone to walk through the code, since exceptions share similarities with the &lt;a href=&quot;https://stackoverflow.com/questions/3329390/difference-between-goto-and-throw&quot;&gt;sometimes criticized&lt;/a&gt; &lt;code class=&quot;language-text&quot;&gt;GOTO&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;And when we return &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;, we&apos;re breaking the &lt;strong&gt;design principle&lt;/strong&gt; that &quot;a method should return a &lt;strong&gt;single type&lt;/strong&gt;&quot;. Not adhering to this can lead to misuse of our methods from clients.&lt;/p&gt;
&lt;p&gt;We&apos;ve half solved this problem in a previous article where we &lt;a href=&quot;/articles/enterprise-typescript-nodejs/handling-errors-result-class/&quot;&gt;explored the use of a &lt;code class=&quot;language-text&quot;&gt;Result&lt;/code&gt; class&lt;/a&gt; to mitigate the &lt;em&gt;jerky&lt;/em&gt; behaviour of throwing errors all over the place. And we&apos;re also able to determine if a &lt;code class=&quot;language-text&quot;&gt;Result&lt;/code&gt; is a &lt;strong&gt;success&lt;/strong&gt; or a &lt;strong&gt;failure&lt;/strong&gt; through &lt;code class=&quot;language-text&quot;&gt;Result.ok&amp;lt;T&amp;gt;&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Result.fail&amp;lt;T&amp;gt;&lt;/code&gt;, but there&apos;s something missing...&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Errors have a place in the domain as well, and they deserve to be modeled as to be modeled as domain concepts&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Since errors account for so much of program behaviour, we can&apos;t pretend to ignore them. And if we&apos;re serious about object-modeling, when we express our errors as &lt;strong&gt;domain concepts&lt;/strong&gt;, our domain model becomes a lot richer and says a lot more about the actual problem.&lt;/p&gt;
&lt;p&gt;That leads to improved readability and less bugs.&lt;/p&gt;
&lt;p&gt;Let me ask you, for something &lt;em&gt;really important&lt;/em&gt;, which would you rather receive if something went wrong?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Something brok, sorry :p haha&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Failure results&lt;/span&gt;
  CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UsernameTakenError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; 
  CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EmailInvalidError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; 
  CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountAlreadyExistsError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InsecurePasswordError
  &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;token comment&quot;&gt;// Success&lt;/span&gt;
  Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here&apos;s what you should expect to know by the end of this article:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Why expressing errors explicitly is important to domain modeling&lt;/li&gt;
&lt;li&gt;How to expressively represent errors using types&lt;/li&gt;
&lt;li&gt;How to and why to organize all errors by &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;Use Cases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;How to elegantly connect errors to &lt;a href=&quot;https://expressjs.com/&quot;&gt;Express.js&lt;/a&gt; API responses&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;How-common-approaches-to-handling-errors-fail-to-express-domain-concepts&quot; style=&quot;position:relative;&quot;&gt;How common approaches to handling errors fail to express domain concepts&lt;a href=&quot;#How-common-approaches-to-handling-errors-fail-to-express-domain-concepts&quot; aria-label=&quot;How common approaches to handling errors fail to express domain concepts permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We briefly mentioned this, but two very common (and fragile) approaches to handling errors I&apos;ve seen are to either &lt;strong&gt;(1) Return null&lt;/strong&gt; or &lt;strong&gt;(2) Log and throw&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;1-Return-null&quot; style=&quot;position:relative;&quot;&gt;(1) Return null&lt;a href=&quot;#1-Return-null&quot; aria-label=&quot;1 Return null permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Consider we had a simple JavaScript function to &lt;strong&gt;Create a User&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isEmailValid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validateEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isPasswordValid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validatePassword&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isEmailValid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Email invalid&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isPasswordValid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Password invalid&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You&apos;ve seen code like this before. You&apos;ve also written code like this. I know I have.&lt;/p&gt;
&lt;p&gt;The truth is, it&apos;s not great. Returning &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt; is a little bit &lt;strong&gt;lazy&lt;/strong&gt; because it requires the caller to be aware of the fact that a &lt;em&gt;failure&lt;/em&gt; to produce a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; will actually produce a &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That provokes mistrust and clutters code with &lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;-checks everywhere&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// success&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// fail&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Not only that, but there are &lt;strong&gt;two separate failure states&lt;/strong&gt; that could occur here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The email could be invalid&lt;/li&gt;
&lt;li&gt;The password could be invalid&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Returning &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt; fails to &lt;em&gt;differentiate&lt;/em&gt; between these two errors. We&apos;ve actually lost expressiveness of our &lt;strong&gt;domain model&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Consider if we wanted our API to return &lt;strong&gt;separate error messages&lt;/strong&gt; for those errors?&lt;/p&gt;
&lt;p&gt;That requirement might lead us to &lt;strong&gt;(2) Log and throw&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;2-Log-and-throw&quot; style=&quot;position:relative;&quot;&gt;(2) Log and throw&lt;a href=&quot;#2-Log-and-throw&quot; aria-label=&quot;2 Log and throw permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Here&apos;s another common (non-optimal) approach to error handling.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isEmailValid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validateEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isPasswordValid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validatePassword&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isEmailValid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Email invalid&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;The email was invalid&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isPasswordValid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Password invalid&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;The password was invalid&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this case, we do get back an &lt;strong&gt;error message&lt;/strong&gt; from the &lt;code class=&quot;language-text&quot;&gt;Error&lt;/code&gt;, but manually throwing errors means having to surround lots of &lt;em&gt;your own code&lt;/em&gt; in &lt;code class=&quot;language-text&quot;&gt;try-catch&lt;/code&gt; blocks.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Fragile code&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;The email was invalid&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// handle&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;The password was invalid&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// handle&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Typically, we should aim to reserve &lt;code class=&quot;language-text&quot;&gt;try-catch&lt;/code&gt; blocks for operations that interact with the outside world &lt;u&gt;(ie: &lt;em&gt;we&apos;re&lt;/em&gt; not the ones throwing errors)&lt;/u&gt;, like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Operations against a database&lt;/li&gt;
&lt;li&gt;Operations utilizing an external service (API, etc)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While that&apos;s an issue, the larger problem at hand is still that we&apos;re not really expressing our possible error states effectively. Refactoring this to TypeScript and expressing errors with &lt;strong&gt;types&lt;/strong&gt; is a start. &lt;/p&gt;
&lt;h2 id=&quot;A-better-approach-to-handling-errors&quot; style=&quot;position:relative;&quot;&gt;A better approach to handling errors&lt;a href=&quot;#A-better-approach-to-handling-errors&quot; aria-label=&quot;A better approach to handling errors permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Tldr?&lt;/b&gt; View the code on GitHub right &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/stemmlerjs/white-label/blob/feature/either-monad/src/functional-error-handling.ts&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We were able to get pretty far with the &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt; class, but the biggest fallback is that while there is often one possible &lt;strong&gt;success&lt;/strong&gt; state, there are several &lt;strong&gt;error&lt;/strong&gt; states. &lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt; class doesn&apos;t allow us to express those several other error states.&lt;/p&gt;
&lt;p&gt;Consider a &lt;code class=&quot;language-text&quot;&gt;CreateUser&lt;/code&gt; &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use case&lt;/a&gt; given a &lt;code class=&quot;language-text&quot;&gt;username&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;password&lt;/code&gt;. What are all of the possible things &lt;strong&gt;that could go &lt;em&gt;right&lt;/em&gt;&lt;/strong&gt;?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The user was successfully created&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OK, and what about all of the things that could go wrong?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The email was invalid&lt;/li&gt;
&lt;li&gt;A user already has this username&lt;/li&gt;
&lt;li&gt;A user already exists with this email&lt;/li&gt;
&lt;li&gt;The password doesn&apos;t meet certain security criteria&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So from end to end (Express.js API call to the database), we want to either a &lt;code class=&quot;language-text&quot;&gt;201  - Created&lt;/code&gt; if successful, some &lt;code class=&quot;language-text&quot;&gt;40O-x&lt;/code&gt; error code if there was a client error, and a &lt;code class=&quot;language-text&quot;&gt;500-x&lt;/code&gt; error if something broke on our end.&lt;/p&gt;
&lt;p&gt;Let&apos;s set it up.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;&quot;Use Case&quot; refresher&lt;/b&gt;: In a &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;previous article (Better Software Design w/ Application Layer Use Cases)&lt;/a&gt;, we discovered that Use Cases are the &lt;b&gt;features&lt;/b&gt; of our apps, &lt;u&gt;decoupled from controllers&lt;/u&gt; so that they &lt;b&gt;can be tested&lt;/b&gt; without spinning up a webserver.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// UserRepository contract&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IUserRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getUserByUsername&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;username&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getUserByEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Input DTO&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  username&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  password&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At this point, we have a &lt;code class=&quot;language-text&quot;&gt;CreateUserUseCase&lt;/code&gt; which &lt;strong&gt;dependency injects&lt;/strong&gt; an &lt;code class=&quot;language-text&quot;&gt;IUserRepo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;Request&lt;/code&gt; dto requires a &lt;code class=&quot;language-text&quot;&gt;username&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;password&lt;/code&gt; and the return type is going to be either a success or failure of &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;any&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Laying out what we need to check for, we can see that there are several potential error states.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Determine if the email is valid&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// If not, return invalid email error&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Determine if the password is valid&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// if not, return invalid password error&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Determine if the username is taken&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// If it is, return an error expressing that the username was taken&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Determine if the user already registered with this email&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// If they did, return an account created error&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Otherwise, return success&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;Value Objects&lt;/a&gt; to &lt;strong&gt;encapsulate validation logic&lt;/strong&gt;, we can get a &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;Email&amp;gt;&lt;/code&gt; and look inside of it to see if it was successfully created or not.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emailOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Email&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emailOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emailOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; passwordOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Password&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Password&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;passwordOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;passwordOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But still, we&apos;re back at &lt;strong&gt;square one&lt;/strong&gt;, instead of returning &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt; or throwing an error, we&apos;re returning a failed &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt; for &lt;strong&gt;both errors&lt;/strong&gt;, which is still &lt;u&gt;not helping the calling code distinguish between them&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;We need to &lt;strong&gt;create types for these error messages&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here&apos;s how we can do that.&lt;/p&gt;
&lt;h3 id=&quot;Expressing-all-errors-for-the-CreateUser-use-case&quot; style=&quot;position:relative;&quot;&gt;Expressing all errors for the &lt;code class=&quot;language-text&quot;&gt;CreateUser&lt;/code&gt; use case&lt;a href=&quot;#Expressing-all-errors-for-the-CreateUser-use-case&quot; aria-label=&quot;Expressing all errors for the CreateUser use case permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&apos;s first standarize an what an error is:&lt;/p&gt;
&lt;h4 id=&quot;DomainError-class&quot; style=&quot;position:relative;&quot;&gt;DomainError class&lt;a href=&quot;#DomainError-class&quot; aria-label=&quot;DomainError class permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DomainError&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  error&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;Contained-error-namespaces&quot; style=&quot;position:relative;&quot;&gt;Contained error namespaces&lt;a href=&quot;#Contained-error-namespaces&quot; aria-label=&quot;Contained error namespaces permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Also, using TypeScript &lt;code class=&quot;language-text&quot;&gt;namespaces&lt;/code&gt;, we can represent all of the errors for the &lt;code class=&quot;language-text&quot;&gt;CreateUser&lt;/code&gt; use case with:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/**
 * @desc General application errors (few of these as possible)
 * @http 500
 */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; AppError &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UnexpectedError&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;DomainError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;err&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;An unexpected error occurred.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; err
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UnexpectedError &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UnexpectedError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * @desc CreateUser errors
 */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; CreateUserError &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UsernameTakenError&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;DomainError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;    
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;username&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;The username &quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;username&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; has already been taken.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;username&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UsernameTakenError &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UsernameTakenError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;username&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EmailInvalidError&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;DomainError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;    
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;The email &quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;email&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; is invalid.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; EmailInvalidError &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EmailInvalidError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AccountAlreadyExistsError&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;DomainError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;    
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;The account associated with this email already exists.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AccountAlreadyExistsError &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AccountAlreadyExistsError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InsecurePasswordError&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;DomainError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;    
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;The password provided wasn&apos;t up to security standards.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; InsecurePasswordError &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InsecurePasswordError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This was possible by making a couple of changes to our old &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt; class:&lt;/p&gt;
&lt;h4 id=&quot;Updated-ResultT-class&quot; style=&quot;position:relative;&quot;&gt;Updated &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt; class&lt;a href=&quot;#Updated-ResultT-class&quot; aria-label=&quot;Updated ResultT class permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; isSuccess&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; isFailure&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; _value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;isSuccess&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isSuccess &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;InvalidOperation: A result cannot be successful and contain an error&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isSuccess &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;InvalidOperation: A failing result needs to contain an error message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; isSuccess&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;freeze&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, we easily represent can go back to our use case change the &lt;strong&gt;signature of our response&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EmailInvalidError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; 
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountAlreadyExistsError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InsecurePasswordError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UsernameTakenError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;AppError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UnexpectedError&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&apos;s better, but what if there was a better way for us to be able to &lt;strong&gt;group&lt;/strong&gt; and separate the &lt;em&gt;success&lt;/em&gt; results from the &lt;em&gt;error&lt;/em&gt; results?&lt;/p&gt;
&lt;h3 id=&quot;Introducing-the-Either-class&quot; style=&quot;position:relative;&quot;&gt;Introducing the &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt; class&lt;a href=&quot;#Introducing-the-Either-class&quot; aria-label=&quot;Introducing the Either class permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt; is a &lt;code class=&quot;language-text&quot;&gt;union&lt;/code&gt; type which is either &lt;code class=&quot;language-text&quot;&gt;Left&lt;/code&gt; (for failure) or &lt;code class=&quot;language-text&quot;&gt;Right&lt;/code&gt; (for success).&lt;/p&gt;
&lt;p&gt;Check out the code, via &lt;a href=&quot;https://medium.com/inato/expressive-error-handling-in-typescript-and-benefits-for-domain-driven-design-70726e061c86&quot;&gt;Bruno Vegreville&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;Either-monad&quot; style=&quot;position:relative;&quot;&gt;Either monad&lt;a href=&quot;#Either-monad&quot; aria-label=&quot;Either monad permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Left&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Right&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Left&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;readonly&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;isLeft&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; Left&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;isRight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; Right&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Right&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;readonly&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;isLeft&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; Left&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;isRight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; Right&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; left &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;l&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; right &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Right&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Equipped with this, we:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get the same observable behaviour from the &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt; class, but now we can also&lt;/li&gt;
&lt;li&gt;...segregate success responses from failure responses&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&apos;s the updated &lt;code class=&quot;language-text&quot;&gt;CreateUserUseCase&lt;/code&gt; using the &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt; class, returning &lt;code class=&quot;language-text&quot;&gt;Left&lt;/code&gt;s for errors and &lt;code class=&quot;language-text&quot;&gt;Right&lt;/code&gt; for success results.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
  CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UsernameTakenError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; 
  CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EmailInvalidError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; 
  CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountAlreadyExistsError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InsecurePasswordError
  &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
  Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// OK &lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Response&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Response&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// We&apos;ve also updated our email Value Object classes &lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// to return the failure results&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emailOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EmailInvalidError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
      Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Email&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; email &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emailOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isLeft&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emailOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Same thing with the Password Value Object&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; passwordOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InsecurePasswordError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
      Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Password&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Password&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;passwordOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isLeft&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;passwordOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;userByUsername&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; userByEmail&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUserByUsername&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;username&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUserByEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; usernameTaken &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;userByUsername &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; accountCreated &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;userByEmail &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// More errors we know about can be expressed this way&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;usernameTaken&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UsernameTakenError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;username&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;accountCreated&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EmailInvalidError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Success resultt&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Any uncaught error&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AppError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UnexpectedError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice that even the &lt;code class=&quot;language-text&quot;&gt;Email&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Password&lt;/code&gt; Value Objects can &lt;strong&gt;express&lt;/strong&gt; and &lt;strong&gt;segregate&lt;/strong&gt; their errors and success states?&lt;/p&gt;
&lt;p&gt;Here&apos;s the &lt;code class=&quot;language-text&quot;&gt;Email&lt;/code&gt; value object for example:&lt;/p&gt;
&lt;h4 id=&quot;Email-value-object&quot; style=&quot;position:relative;&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Email&lt;/code&gt; value object&lt;a href=&quot;#Email-value-object&quot; aria-label=&quot;Email value object permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Email&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ValueObject&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;EmailProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; EmailProps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isEmailValid&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Naive validation&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; EmailProps
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EmailInvalidError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Email&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isEmailValid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Email&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EmailInvalidError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Hooking-it-all-up-to-an-Expressjs-API-controller&quot; style=&quot;position:relative;&quot;&gt;Hooking it all up to an Express.js API controller&lt;a href=&quot;#Hooking-it-all-up-to-an-Expressjs-API-controller&quot; aria-label=&quot;Hooking it all up to an Expressjs API controller permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Last thing we want to figure out how to do is to get this working with our &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-consistent-expressjs-controllers/&quot;&gt;Base Controller&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since we&apos;ve already encapsulated all of the potential Express.js error and success response messages, our code will look a lot more expressive.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; useCase&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CreateUserUseCase&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;useCase&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CreateUserUseCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;useCase &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; useCase&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeImpl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;useCase&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// If the use case has a failure response of some sort&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isLeft&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; error &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Switch on the response, map it to the correct HTTP error.&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UsernameTakenError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;conflict&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EmailInvalidError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clientError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountAlreadyExistsError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;conflict&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InsecurePasswordError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clientError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
    
    &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Because the result of the use case is of the &lt;code class=&quot;language-text&quot;&gt;Either&lt;/code&gt; type, it forces the caller to look into if the request was successful or not, and handle them accordingly.&lt;/p&gt;
&lt;p&gt;By using a &lt;code class=&quot;language-text&quot;&gt;switch&lt;/code&gt; statement on the &lt;code class=&quot;language-text&quot;&gt;constructor&lt;/code&gt;, we can get direct access to the &lt;code class=&quot;language-text&quot;&gt;type&lt;/code&gt; of error before  mapping it to the correct Express.js HTTP response code.&lt;/p&gt;
&lt;h3 id=&quot;Composing-the-controller-with-the-use-case&quot; style=&quot;position:relative;&quot;&gt;Composing the controller with the use case&lt;a href=&quot;#Composing-the-controller-with-the-use-case&quot; aria-label=&quot;Composing the controller with the use case permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In order to use this controller in our app, we need to create it and then export it so that it can be used up by the main Express.js app.&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;modules/users/useCases/createUser/index.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CreateUserUseCase &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./CreateUserUseCase&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CreateUserController &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./CreateUserController&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;modules/users&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// repo instance exported from module&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Create the CreateUserUseCase by injecting a UserRepo instance&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; createUserCase &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserUseCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Create the CreateUserController by injecting the CreateUserUseCase&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; createUserController &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;createUserCase&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Export both from this module&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  createUserCase&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  createUserController
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Connecting-a-controller-instance-to-a-route-handler&quot; style=&quot;position:relative;&quot;&gt;Connecting a controller instance to a route handler&lt;a href=&quot;#Connecting-a-controller-instance-to-a-route-handler&quot; aria-label=&quot;Connecting a controller instance to a route handler permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;filename&quot;&gt;modules/users/infra/http/routes/index.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; express &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;express&apos;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Grab the instance of the CreateUserController from the useCases&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createUserController &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../../useCases/createUser&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userRouter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Router&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

userRouter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;token comment&quot;&gt;// Hook the controller instance up to a POST call&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; createUserController&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userRouter &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Export the router so the main app can use it&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then we can hook this up to the main Express.js app instance with:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;app/index.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; express &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;express&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userRouter &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;modules/users/infra/http/routes&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Other handlers&lt;/span&gt;

app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/users&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; userRouter&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Express app started!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In conclusion, our project structure could look a little something like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;src
  └ modules
    └ &lt;span class=&quot;token function&quot;&gt;users&lt;/span&gt;                          &lt;span class=&quot;token comment&quot;&gt;# &apos;Users&apos; subdomain&lt;/span&gt;
      └ domain                       &lt;span class=&quot;token comment&quot;&gt;# Domain models (entities, value objects)&lt;/span&gt;
        └ Email.ts                   &lt;span class=&quot;token comment&quot;&gt;# Email (value object)&lt;/span&gt;
        └ Password.ts                &lt;span class=&quot;token comment&quot;&gt;# Password (value object)&lt;/span&gt;
        └ User.ts                    &lt;span class=&quot;token comment&quot;&gt;# User (aggregate / entity)             &lt;/span&gt;
      └ infra                        &lt;span class=&quot;token comment&quot;&gt;# Infrastructure layer concerns (webservers, caches, etc)&lt;/span&gt;
        └ http
          └ routes
            └ index.ts               &lt;span class=&quot;token comment&quot;&gt;# Export a user router&lt;/span&gt;
        └ repos                      
          └ UserRepo.ts              &lt;span class=&quot;token comment&quot;&gt;# Facade to the sequelize user models&lt;/span&gt;
      └ useCases                     &lt;span class=&quot;token comment&quot;&gt;# All of the application layer features&lt;/span&gt;
        └ createUser                 &lt;span class=&quot;token comment&quot;&gt;# Feature/Use Case #1 - Create a user &lt;/span&gt;
          └ CreateUserUseCase.ts     &lt;span class=&quot;token comment&quot;&gt;# Use Case (also known as application service)&lt;/span&gt;
          └ CreateUserController.ts  &lt;span class=&quot;token comment&quot;&gt;# Create user controller&lt;/span&gt;
          └ CreateUserErrors.ts      &lt;span class=&quot;token comment&quot;&gt;# Any use case-specific errors&lt;/span&gt;
          └ index.ts                 &lt;span class=&quot;token comment&quot;&gt;# Export controller (required) and use case (optional) from this module&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;Domain-Driven-Design-for-the-win&quot; style=&quot;position:relative;&quot;&gt;Domain-Driven Design for the win&lt;a href=&quot;#Domain-Driven-Design-for-the-win&quot; aria-label=&quot;Domain Driven Design for the win permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is exactly the type of thinking that we do when we&apos;re working on &lt;a href=&quot;https://www.essentialist.dev/master-the-essentials-of-software-design-with-typescript&quot;&gt;Domain-Driven&lt;/a&gt; projects. Errors are a part of the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;Domain layer&lt;/a&gt; in our &lt;strong&gt;clean/layered architecture&lt;/strong&gt; and this is an excellent way to start representing them accordingly.&lt;/p&gt;
&lt;hr&gt;
&lt;p class=&quot;special-quote&quot;&gt;If you&apos;d like to see the code in it&apos;s entirety, it&apos;s right &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/stemmlerjs/white-label/blob/feature/either-monad/src/functional-error-handling.ts&quot;&gt;here&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;h2 id=&quot;Additional-reading&quot; style=&quot;position:relative;&quot;&gt;Additional reading&lt;a href=&quot;#Additional-reading&quot; aria-label=&quot;Additional reading permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/inato/expressive-error-handling-in-typescript-and-benefits-for-domain-driven-design-70726e061c86&quot;&gt;Expressive Error Handling for Domain-Driven Design, by Bruno Vegreville&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html&quot;&gt;TypeScript 2.1 Release Notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/12739149/typescript-type-signatures-for-functions-with-variable-argument-counts&quot;&gt;Type Signatures for functions with variable argument counts&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/namespaces.html&quot;&gt;TypeScript namespaces&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.to/_gdelgado/type-safe-error-handling-in-typescript-1p4n&quot;&gt;Type Safe Error Handling in TypeScript&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/36332665/how-to-use-instanceof-in-a-switch-statement&quot;&gt;How to use instanceof in a switch statement&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[An Introduction to Domain-Driven Design (DDD)]]></title><description><![CDATA[Also from the Domain-Driven Design with TypeScript article series. Have you ever worked on a codebase where it felt like "the more code I…]]></description><link>https://khalilstemmler.com/articles/domain-driven-design-intro/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/domain-driven-design-intro/</guid><pubDate>Tue, 30 Jul 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Also from the &lt;strong&gt;&lt;a href=&quot;/articles/categories/domain-driven-design/&quot;&gt;Domain-Driven Design with TypeScript&lt;/a&gt;&lt;/strong&gt; article series&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Have you ever worked on a codebase where it felt like &quot;the more code I add, the more complex it gets&quot;?&lt;/p&gt;
&lt;p&gt;Have you ever wondered, &quot;how &lt;em&gt;do you&lt;/em&gt; organize business logic anyways&quot;?&lt;/p&gt;
&lt;p&gt;Or have you ever been in the situation where you&apos;re nervous to add new code to an existing codebase in the fear that you&apos;ll break something else in a completely different part of the code somewhere?&lt;/p&gt;
&lt;p&gt;What about enterprise companies? How are &lt;em&gt;they&lt;/em&gt; doing it? Their codebases must be massive. How do they get anything done? How do &lt;em&gt;they&lt;/em&gt; manage that complexity? &lt;/p&gt;
&lt;p&gt;How are able they able to break off large bodies of code, assign them to teams, and then integrate all the teams together? &lt;/p&gt;
&lt;p&gt;I&apos;ve wondered all of this while coding on a 3 year old Node.js app with a line count pushing ~150K+.&lt;/p&gt;
&lt;p&gt;I came across &lt;strong&gt;Domain-Driven Design&lt;/strong&gt; when I realized I needed it the most.&lt;/p&gt;
&lt;h2 id=&quot;Quick-history-about-my-experience-with-DDD&quot; style=&quot;position:relative;&quot;&gt;Quick history about my experience with DDD&lt;a href=&quot;#Quick-history-about-my-experience-with-DDD&quot; aria-label=&quot;Quick history about my experience with DDD permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In 2017, I started working on an application called &lt;strong&gt;Univjobs&lt;/strong&gt;, a marketplace for Canadian students and recent-grads to find co-op jobs, gigs and entry-level jobs and internships.&lt;/p&gt;
&lt;p&gt;The MVP was pretty simple. Students could sign up, create their profile and apply to jobs. Employers could sign up, post jobs, browse students and invite them to apply to the jobs they&apos;ve posted.&lt;/p&gt;
&lt;p&gt;Since 2017, we&apos;ve iterated many times, adjusting and encorporating features based on feedback from students and employers such as job recommendations, interviews, an Applicant Tracking System and several portals to integrate with the existing platform (developers, campus reps, etc).&lt;/p&gt;
&lt;p&gt;Eventually, the codebase had became so large that adding new features on top of it took &lt;u&gt;nearly 3x&lt;/u&gt; the amount of time it would have taken when I first started. &lt;/p&gt;
&lt;p&gt;Lack of encapsulation and object-oriented design were to blame.&lt;/p&gt;
&lt;p&gt;I had an &lt;a href=&quot;/wiki/anemic-domain-model&quot;&gt;Anemic Domain Model&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/wiki/anemic/chart.svg&quot; alt=&quot;anemic domain model&quot;&gt;&lt;/p&gt;
&lt;p&gt;It was at this point I started to seek out solutions to the problem.&lt;/p&gt;
&lt;h2 id=&quot;About-Domain-Driven-Design&quot; style=&quot;position:relative;&quot;&gt;About Domain-Driven Design&lt;a href=&quot;#About-Domain-Driven-Design&quot; aria-label=&quot;About Domain Driven Design permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Domain-Driven Design is an approach to software development that aims to &lt;strong&gt;match the mental model&lt;/strong&gt; of the problem domain we&apos;re addressing.&lt;/p&gt;
&lt;p&gt;The goals of DDD are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Discover the domain model by interacting with domain experts and agreeing upon a common set of terms to refer to processes, actors and any other phenomenon that occurs in the domain.&lt;/li&gt;
&lt;li&gt;Take those newly discovered terms and embed them in the code, creating a rich domain model that reflects the actual living, breathing business and it&apos;s rules.&lt;/li&gt;
&lt;li&gt;Protect that domain model from all the other technical intricacies involved in creating a web application. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Initially conceptualized by Eric Evans who wrote the &lt;a href=&quot;https://www.amazon.ca/gp/product/0321125215/ref=as_li_tl?ie=UTF8&amp;#x26;camp=15121&amp;#x26;creative=330641&amp;#x26;creativeASIN=0321125215&amp;#x26;linkCode=as2&amp;#x26;tag=stemmlerjs09-20&amp;#x26;linkId=170eea6252cf16310fc9e7694209e5ed&quot;&gt;&lt;em&gt;bible&lt;/em&gt; of DDD&lt;/a&gt; (famously known as the Blue Book), DDD&apos;s primary technical benefits are that it enables you to write &lt;strong&gt;expressive&lt;/strong&gt;, &lt;strong&gt;rich&lt;/strong&gt; and &lt;strong&gt;encapsulated&lt;/strong&gt; software that are testable, scalable and maintainable.&lt;/p&gt;
&lt;h3 id=&quot;Discovering-the-Ubiquitous-Language&quot; style=&quot;position:relative;&quot;&gt;Discovering the Ubiquitous Language&lt;a href=&quot;#Discovering-the-Ubiquitous-Language&quot; aria-label=&quot;Discovering the Ubiquitous Language permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;Ubiquitous Language&lt;/strong&gt; (which is a fancy DDD term for the common language that best describes the domain model concepts) can only be learned by &lt;strong&gt;talking with the domain experts&lt;/strong&gt;. Once agreed upon, it enables developers to connect what the software implementation to what &lt;em&gt;actually occurs&lt;/em&gt; in the real world. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If we&apos;re building an app that helps recruiters hire talent, we need to spend some time understanding the domain language and processes that exist from the recruiters&apos; perspective.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That means actually talking to the domain experts.&lt;/p&gt;
&lt;p&gt;Knowing the names of the constructs that we&apos;re about to model enables us to create rich &lt;strong&gt;domain models&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Modeling-the-Domain&quot; style=&quot;position:relative;&quot;&gt;Modeling the Domain&lt;a href=&quot;#Modeling-the-Domain&quot; aria-label=&quot;Modeling the Domain permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are huge payoffs in domain modeling. When our code lines up with the real life domain, we end up with a &lt;a href=&quot;/articles/typescript-domain-driven-design/ddd-vs-crud-design/&quot;&gt;rich declarative design&lt;/a&gt; that will enable us to make changes and add new features exponentially faster.&lt;/p&gt;
&lt;h3 id=&quot;Prerequisite-Knowledge&quot; style=&quot;position:relative;&quot;&gt;Prerequisite Knowledge&lt;a href=&quot;#Prerequisite-Knowledge&quot; aria-label=&quot;Prerequisite Knowledge permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You must at least &lt;em&gt;this tall&lt;/em&gt; to ride this ride.&lt;/p&gt;
&lt;p&gt;Jokes aside, Domain-Driven Design has a steep learning-curve. I won&apos;t lie about that. &lt;/p&gt;
&lt;p&gt;Domain-Driven Developers need to be comfortable with the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Object-Oriented Programming Basics &lt;/li&gt;
&lt;li&gt;Object-Oriented Programming Design Principles (composition &gt; inheritance, referring to abstractions, SOLID Principles)&lt;/li&gt;
&lt;li&gt;General Design Principles (&lt;a href=&quot;/wiki/yagni&quot;&gt;YAGNI&lt;/a&gt;, KISS, DRY)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Object-Oriented Programming is not strictly necessary to be successful with Domain Driven Design, but it does go with the natural contours of the patterns Domain-Driven Design has established.&lt;/p&gt;
&lt;p&gt;To be able to move quickly, DDD does require some fundamental knowledge of software design patterns. It&apos;s a lot harder to do DDD well if we make a mess. That&apos;s why principles like YAGNI, KISS and DRY are even more important in order to iteratively improve a design.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;The software design roadmap&lt;/b&gt;: Check out this &lt;a href=&quot;/articles/software-design-architecture/full-stack-software-design/&quot;&gt; roadmap&lt;/a&gt; I put together in order to figure out what you need to know in order to be most comfortable with Domain-Driven Design (which is right at the end of the roadmap).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In order to go fast, we must go well.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;There-is-a-construct-for-everything&quot; style=&quot;position:relative;&quot;&gt;There is a construct for everything&lt;a href=&quot;#There-is-a-construct-for-everything&quot; aria-label=&quot;There is a construct for everything permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Much of what makes frameworks so popular is that there is a pre-established way to do everything. When modeling the domain layer in DDD, there are already pre-established building blocks for every task.&lt;/p&gt;
&lt;p&gt;See &lt;a target=&quot;_self&quot; href=&quot;#building-blocks&quot;&gt;here&lt;/a&gt; for the list of building blocks for DDD applications.&lt;/p&gt;
&lt;h2 id=&quot;Protecting-the-Domain-Layer&quot; style=&quot;position:relative;&quot;&gt;Protecting the Domain Layer&lt;a href=&quot;#Protecting-the-Domain-Layer&quot; aria-label=&quot;Protecting the Domain Layer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In order to do DDD well, we need to keep the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;SOLID principles&lt;/a&gt; in mind, organize a central &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;domain layer&lt;/a&gt; at the core of our &lt;a href=&quot;https://herbertograca.com/2017/08/03/layered-architecture/&quot;&gt;Layered Architecture&lt;/a&gt; and use a LOT of &lt;a href=&quot;/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;dependency inversion &amp;#x26; injection&lt;/a&gt; in order to connect interface adapters to persistence, web and external technologies. &lt;/p&gt;
&lt;p&gt;We don&apos;t want these infrastructrual things to sully our clean, fast, and testable domain model.&lt;/p&gt;
&lt;p&gt;We want to keep frameworks, databases, caches, web servers, and anything else techy and not related to the domain model to a distance.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;A large part of DDD is protecting the domain model by using a layered architecture. Check out &lt;a href=&quot;/articles/software-design-architecture/organizing-app-logic/&quot;&gt;this article&lt;/a&gt; on what each layer is responsible for.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-intro/clean.jpg&quot; alt=&quot;clean architecture&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;caption&quot;&gt;&quot;The Clean Architecture&quot;. From the golden Uncle Bob archives. Also known as a Layered Architecture, Ports &amp; Adapters, Hexigonal, etc.&lt;/div&gt;
&lt;h3 id=&quot;JavaScript-community-on-Enterprise-Application-Development&quot; style=&quot;position:relative;&quot;&gt;JavaScript community on Enterprise Application Development&lt;a href=&quot;#JavaScript-community-on-Enterprise-Application-Development&quot; aria-label=&quot;JavaScript community on Enterprise Application Development permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I studied Java in high-school and University. Like a lot of my peers, I didn&apos;t really LOVE Java a whole lot because: &lt;/p&gt;
&lt;p&gt;a) We hated seeing red lines in the compiler all the time. This was scary for a 1st year University student learning how to program and &lt;/p&gt;
&lt;p&gt;b) The community around Java appeared to be mostly focused on enterprise application patterns and frameworks. Concepts like POJOs, JavaBeans, dependency injection and aspect oriented programming were not &lt;em&gt;cool&lt;/em&gt; nor did we aim to understand them or their uses (I should also mention, these were the early days of learning when some of us thought Java and JavaScript were the same thing 😜). &lt;/p&gt;
&lt;p&gt;When I first picked up a book on Node.js and was introduced to JavaScript, I was blown away by all the cool things you can do with JavaScript, HTML and CSS. &lt;/p&gt;
&lt;p&gt;The community was much more interesting than the Java community to me as a musician and a gamer (at the time).&lt;/p&gt;
&lt;p&gt;Like many others, we learned how to build Node.js backends through YouTube, &lt;a href=&quot;https://scotch.io&quot;&gt;Scotch.io&lt;/a&gt;, &lt;a href=&quot;https://udemy.com&quot;&gt;Udemy&lt;/a&gt; and &lt;a href=&quot;https://udacity.com&quot;&gt;Udacity&lt;/a&gt; courses. This was also the extent to which a large number of developers from my generation learned about software design.&lt;/p&gt;
&lt;p&gt;Model + view + controller.&lt;/p&gt;
&lt;p&gt;&lt;a id=&quot;building-blocks&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This works great for a large number of RESTful web backends, but for applications where the problem domain is complex, we need to break down the &quot;model&quot; part even further&lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;To do that, we use the &lt;strong&gt;building blocks&lt;/strong&gt; of DDD.&lt;/p&gt;
&lt;h2 id=&quot;Building-Blocks&quot; style=&quot;position:relative;&quot;&gt;Building Blocks&lt;a href=&quot;#Building-Blocks&quot; aria-label=&quot;Building Blocks permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Very briefly, these are the main technical artifacts involved in implementing DDD. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-intro/ddd-diagram.svg&quot; alt=&quot;DDD Diagram&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Entities&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;/articles/typescript-domain-driven-design/entities/&quot;&gt;Entities&lt;/a&gt;&lt;a href=&quot;#Entities&quot; aria-label=&quot;Entities permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Domain objects that we care to &lt;em&gt;uniquely&lt;/em&gt; identify. &lt;/p&gt;
&lt;p&gt;Things like: &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Job&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Comment&lt;/code&gt;, etc.&lt;/p&gt;
&lt;p&gt;Entities live a life enabling them to be &lt;code class=&quot;language-text&quot;&gt;created&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;updated&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;persisted&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;retrieved&lt;/code&gt; from persistence, &lt;code class=&quot;language-text&quot;&gt;archived&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;deleted&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;Entities are compared by their &lt;strong&gt;unique identifier&lt;/strong&gt; (usually a UUID or Primary Key of some sort).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd/entity-lifecycle.svg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Value-Objects&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;Value Objects&lt;/a&gt;&lt;a href=&quot;#Value-Objects&quot; aria-label=&quot;Value Objects permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Value objects have no identity. They are &lt;em&gt;attributes&lt;/em&gt; of Entities. &lt;/p&gt;
&lt;p&gt;Think: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Name&lt;/code&gt; as a Value Object on a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;JobStatus&lt;/code&gt; as a Value Object on &lt;code class=&quot;language-text&quot;&gt;Job&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;PostTitle&lt;/code&gt; as a Value Object on &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Value Objects are compared by their &lt;strong&gt;structrual equality&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// A valid (yet not very efficient) way to compare Value Objects&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; khalilName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Khalil&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Stemmler&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; nick &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Nick&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Cave&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;khalil&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nick&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Aggregate&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;Aggregate&lt;/a&gt;&lt;a href=&quot;#Aggregate&quot; aria-label=&quot;Aggregate permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;These are a collection of entities are that bound together by an aggregate root. The aggregate root is the thing that we refer to for lookups. No members from within the aggregate boundary can be referred to directly from anything external to the aggregate. This is how the aggregate maintains consistency. &lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;most powerful part about aggregates is that they dispatch Domain Events&lt;/strong&gt; which can be used to &lt;u&gt;co-locate business logic in the appropriate subdomain&lt;/u&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Domain-Services&quot; style=&quot;position:relative;&quot;&gt;Domain Services&lt;a href=&quot;#Domain-Services&quot; aria-label=&quot;Domain Services permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is where we locate domain logic that doesn&apos;t belong to any one object conceptually.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;Domain Services are most often executed by application layer &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;Application Services / Use Cases&lt;/a&gt;. Because Domain Services are a part of the &lt;b&gt;Domain Layer&lt;/b&gt; and adhere to the &lt;a href=&quot;/wiki/dependency-rule/&quot;&gt;dependency rule&lt;/a&gt;, Domain Services aren&apos;t allowed to depend on infrastructure layer concerns like &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;Repositories&lt;/a&gt; to get access to the domain entities that they interact with. Application Services fetch the necessary entities, then pass them to domain services to run allow them to interact.&lt;/p&gt;
&lt;h3 id=&quot;Repository&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;Repository&lt;/a&gt;&lt;a href=&quot;#Repository&quot; aria-label=&quot;Repository permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We use repositories in order to retrieve domain objects from persistence technologies. Using software design principles like the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;Liskov Subsitution Principle&lt;/a&gt; and a layered architecture, we can design this in a way so that we can easily make architecture decisions to switch between an in-memory repository for testing, a MySQL implementation for today, and a MongoDB based implementation 2 years from now.&lt;/p&gt;
&lt;h3 id=&quot;Factory&quot; style=&quot;position:relative;&quot;&gt;Factory&lt;a href=&quot;#Factory&quot; aria-label=&quot;Factory permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We&apos;ll want to create domain objects in many different ways. We map to domain objects using a factory that operates on raw sql rows, raw json, or the &lt;a href=&quot;https://martinfowler.com/eaaCatalog/activeRecord.html&quot;&gt;Active Record&lt;/a&gt; that&apos;s returned from your ORM tool (like Sequelize or TypeORM). &lt;/p&gt;
&lt;p&gt;We might also want to create domain objects from templates using the &lt;a href=&quot;https://www.geeksforgeeks.org/prototype-design-pattern/&quot;&gt;prototype pattern&lt;/a&gt; or through the use of an &lt;a href=&quot;/wiki/abstract-factory&quot;&gt;abstract factory&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Domain-Events&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;/articles/typescript-domain-driven-design/chain-business-logic-domain-events/&quot;&gt;Domain Events&lt;/a&gt;&lt;a href=&quot;#Domain-Events&quot; aria-label=&quot;Domain Events permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;The best part of Domain-Driven Design&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Domain events are simply objects that define some sort of &lt;strong&gt;event&lt;/strong&gt; that occurs in the domain &lt;strong&gt;that domain experts care about&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Typically &lt;a href=&quot;/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;when we&apos;re dealing with CRUD apps&lt;/a&gt;, we add new &lt;strong&gt;domain logic&lt;/strong&gt; that we&apos;ve identified by adding more &lt;code class=&quot;language-text&quot;&gt;if/else&lt;/code&gt; statements.&lt;/p&gt;
&lt;p&gt;However, in complex applications that can become very cumbersome (think &lt;a href=&quot;https://gitlab.com&quot;&gt;Gitlab&lt;/a&gt; or &lt;a href=&quot;https://netflix.com&quot;&gt;Netflix&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Using Domain Events, instead of &lt;em&gt;adding more and more &lt;code class=&quot;language-text&quot;&gt;if/else&lt;/code&gt; blocks&lt;/em&gt; like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// After creating a user, we handle both:&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// 1. Recording a referral (if one was made)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;referred_by_referral_code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// calculate payouts&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// .. there could be a lot more logic here&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Referral&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; code&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;referralCode&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; user_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user_id &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;token comment&quot;&gt;// 2. Sending an email verification email&lt;/span&gt;
    EmailToken&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createToken&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; EmailService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendEmailVerificationEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user_email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// mind you, neither of these 2 additonal things that need to get&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// done are particularly the responsibility of the &quot;user&quot; subdomain&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;caption&quot;&gt;Example of handling domain logic (transaction script-style).&lt;/div&gt;
&lt;p&gt;We can achieve something beautiful like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-intro/events.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;Using &lt;strong&gt;domain services&lt;/strong&gt; (such as the &lt;code class=&quot;language-text&quot;&gt;ReferralFactoryService&lt;/code&gt;) and &lt;strong&gt;application services&lt;/strong&gt; (such as the &lt;code class=&quot;language-text&quot;&gt;EmailService&lt;/code&gt;), Domain Events can be used to  &lt;em&gt;separate the concerns&lt;/em&gt; of the domain logic to be a executed from the subdomain it belongs.&lt;/p&gt;
&lt;p&gt;Domain Events are an excellent way to decouple and chain really complex business logic.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;Technical-Benefits&quot; style=&quot;position:relative;&quot;&gt;Technical Benefits&lt;a href=&quot;#Technical-Benefits&quot; aria-label=&quot;Technical Benefits permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;write testable business-layer logic&lt;/li&gt;
&lt;li&gt;spend less time fixing bugs&lt;/li&gt;
&lt;li&gt;watch a codebase actually improve over time as code gets added to it rather than degrade&lt;/li&gt;
&lt;li&gt;create long-lasting software implementations of complex domains&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Technical-Drawbacks&quot; style=&quot;position:relative;&quot;&gt;Technical Drawbacks&lt;a href=&quot;#Technical-Drawbacks&quot; aria-label=&quot;Technical Drawbacks permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Domain modeling is time-consuming up front and it&apos;s a technique that needs to be learned.&lt;/p&gt;
&lt;p&gt;Because it involves a lot of encapsulation and isolation of the domain model, it can take some time to accomplish.&lt;/p&gt;
&lt;p&gt;Depending on the project, it might be more worthwhile to continue building an &lt;a href=&quot;/wiki/anemic-domain-model&quot;&gt;Anemic Domain Model&lt;/a&gt;. Choosing DDD coincides with a lot of the &lt;a href=&quot;/articles/when-to-use-typescript-guide/&quot;&gt;arguments I made for when it&apos;s right to use TypeScript over JavaScript&lt;/a&gt; for your project. Use DDD for #3 of the &lt;em&gt;3 Hard Software Problems&lt;/em&gt;: The Complex Domain Problem.&lt;/p&gt;
&lt;h1 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I&apos;m really glad you&apos;re here and you&apos;re reading this. &lt;/p&gt;
&lt;p&gt;If you&apos;re Junior Developer or getting started in the world of software architecture and design, I think you&apos;re on the right track.&lt;/p&gt;
&lt;p&gt;Domain-Driven Design has introduced me to a world of software architecture, patterns and principles that I might not have naturally started learning until much later.&lt;/p&gt;
&lt;p&gt;From my own experience, it&apos;s largely a &quot;you don&apos;t know it until you need it&quot; kind of thing where:&lt;/p&gt;
&lt;p&gt;a) you realize you need to model a complex domain and it seems daunting so you try to find the right methology to approach it or&lt;/p&gt;
&lt;p&gt;b) your codebase has become so large that it&apos;s hard to add new features without breaking new things, so you seek the solution to that problem or&lt;/p&gt;
&lt;p&gt;c) someone more experienced than you brings it to your attention&lt;/p&gt;
&lt;p&gt;d) you read my article and you realized &lt;a href=&quot;/wiki/anemic-domain-model&quot;&gt;you have an anemic domain model&lt;/a&gt; and you don&apos;t wish to have one.&lt;/p&gt;
&lt;p&gt;The thing about Domain modeling is that it does take a little bit of time to start to get comfortable with. It can be a bit awkward to get accustomed to organizing your code this way, but when you start to reap the benefits of DDD, I think you&apos;ll naturally prefer to organize your backend code this way over the &lt;a href=&quot;/wiki/anemic-domain-model&quot;&gt;Anemic Domain Model&lt;/a&gt; and &lt;a href=&quot;https://martinfowler.com/eaaCatalog/transactionScript.html&quot;&gt;Transaction Script&lt;/a&gt; approach.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;More in this series so far&lt;/em&gt;..&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/articles/typescript-domain-driven-design/entities/&quot;&gt;Understanding Domain Entities - DDD w/ TypeScript&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/articles/typescript-value-object&quot;&gt;Value Objects - DDD w/ TypeScript&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/articles/auto-increment-or-uuid/&quot;&gt;Using UUIDs instead of Auto-Incremented Primary Keys&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/articles/typescript-domain-driven-design/ddd-vs-crud-design/&quot;&gt;REST-first design is Imperative, DDD is Declarative [Comparison] - DDD w/ TypeScript&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;Implementing DTOs, Mappers &amp;#x26; the Repository Pattern using the Sequelize ORM [with Examples] - DDD w/ TypeScript&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/articles/typescript-domain-driven-design/intention-revealing-interfaces/&quot;&gt;Intention Revealing Interfaces [w/ Examples] - Domain-Driven Design w/ TypeScript&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;How to Design &amp;#x26; Persist Aggregates - Domain-Driven Design w/ TypeScript&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/articles/typescript-domain-driven-design/one-to-many-performance/&quot;&gt;Handling Collections in Aggregates (0-to-Many, Many-to-Many) - Domain-Driven Design w/ TypeScript&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/articles/typescript-domain-driven-design/domain-modeling-1/&quot;&gt;Challenges in Aggregate Design #1 - Domain-Driven Design w/ TypeScript&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/articles/typescript-domain-driven-design/ddd-frontend/&quot;&gt;Does DDD Belong on the Frontend? - Domain-Driven Design w/ TypeScript&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/blogs/domain-driven-design/where-do-domain-events-get-dispatched/&quot;&gt;Where Do Domain Events Get Created? | Domain Driven Design w/ TypeScript&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/articles/typescript-domain-driven-design/chain-business-logic-domain-events/&quot;&gt;Decoupling Logic with Domain Events [Guide] - Domain-Driven Design w/ TypeScript&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;&lt;em&gt;See &lt;a href=&quot;/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;this article&lt;/a&gt; on how to know when MVC isn&apos;t enough&lt;/em&gt;.&lt;/p&gt;
&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[No title]]></title><description><![CDATA[The Dependency Rule In Uncle Bob's book, he describes the dependency rule. That rule specifies that something declared in an outer circle…]]></description><link>https://khalilstemmler.com/wiki/dependency-rule/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/dependency-rule/</guid><pubDate>Tue, 30 Jul 2019 04:05:26 GMT</pubDate><content:encoded>&lt;h3 id=&quot;The-Dependency-Rule&quot; style=&quot;position:relative;&quot;&gt;The Dependency Rule&lt;a href=&quot;#The-Dependency-Rule&quot; aria-label=&quot;The Dependency Rule permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In Uncle Bob&apos;s book, he describes &lt;strong&gt;the dependency rule&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That rule specifies that something declared in an outer circle &lt;u&gt;must not be mentioned in the code by an inner circle&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;That means that code dependencies can only point inwards.&lt;/p&gt;
&lt;p&gt;For example, Domain Layer code can&apos;t depend on Infrastructure Layer code, Infrastructure Layer Code &lt;em&gt;can depend&lt;/em&gt; on Domain Layer code (because it goes inwards).&lt;/p&gt;
&lt;div style=&quot;max-width: 300px;margin: 0 auto;&quot;&gt;
  &lt;img src=&quot;/img/wiki/dependency-rule/the-dependency-rule.svg&quot;/&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;In other diagrams, there are many more layers. The rule still applies.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Why does this matter?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We avoid circular dependencies and keep code testable. The &lt;a href=&quot;/wiki/acyclic-dependencies-principle/&quot;&gt;Acylic Dependency Rule&lt;/a&gt; describes this phenomenon in more detail.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;How does this work?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;By both &lt;a href=&quot;/articles/software-design-architecture/write-testable-code/&quot;&gt;being conscious about how we hook up dependencies&lt;/a&gt;, making sure we only refer to lower layers directly, and using the &lt;a href=&quot;dependency-inversion/&quot;&gt;Dependency Inversion&lt;/a&gt; principle from the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;SOLID Principles&lt;/a&gt; to refer to &lt;em&gt;abstractions&lt;/em&gt; of upper layer concerns (instead of &lt;a href=&quot;/wiki/concrete-class/&quot;&gt;concrete&lt;/a&gt; implementations).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Layered-Architecture-Dependency-Rules&quot; style=&quot;position:relative;&quot;&gt;Layered Architecture Dependency Rules&lt;a href=&quot;#Layered-Architecture-Dependency-Rules&quot; aria-label=&quot;Layered Architecture Dependency Rules permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&apos;s talk about some of the rules we need to follow when we layer our code this way. &lt;/p&gt;
&lt;h3 id=&quot;Domain-Layer&quot; style=&quot;position:relative;&quot;&gt;Domain Layer&lt;a href=&quot;#Domain-Layer&quot; aria-label=&quot;Domain Layer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;OK, let&apos;s map out some common scenarios.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Everything&lt;/strong&gt; can depend on &lt;strong&gt;Domain Objects&lt;/strong&gt; (entities, value objects, domain services) within the domain layer.&lt;/p&gt;
&lt;p&gt;But &lt;strong&gt;Domain Objects&lt;/strong&gt; can depend on &lt;em&gt;exactly nothing outside the domain layer&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;That&apos;s because the domain layer contains the &lt;strong&gt;highest level policy&lt;/strong&gt;. Everything else depends on it.&lt;/p&gt;
&lt;p&gt;The domain layer should be &lt;a href=&quot;/wiki/stable-dependency-principle/&quot;&gt;the most stable dependency&lt;/a&gt; and depend on classes from no other layer except itself in order to prevent &lt;a href=&quot;/wiki/acyclic-dependencies-principle/&quot;&gt;cycles&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Application-Use-Case-Layer&quot; style=&quot;position:relative;&quot;&gt;Application (Use Case) Layer&lt;a href=&quot;#Application-Use-Case-Layer&quot; aria-label=&quot;Application Use Case Layer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Use cases &lt;strong&gt;heavily&lt;/strong&gt; rely on the only layer underneath it (domain) but also needs access to infrastructure layer things like &lt;strong&gt;repositories&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Try creating any use cases without access to persistence. Most of them need it. Take the &lt;code class=&quot;language-text&quot;&gt;CreateUserUseCase&lt;/code&gt; from the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/functional-error-handling/&quot;&gt;&quot;Functional Error Handling with Express.js and DDD&quot;&lt;/a&gt; guide:&lt;/p&gt;
&lt;div class=&quot;filename&quot;&gt;modules/users/useCases/createUser/CreateUserUseCase.ts&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
  CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UsernameTakenError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; 
  CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EmailInvalidError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; 
  CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountAlreadyExistsError &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InsecurePasswordError
  &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
  Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// OK &lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Response&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// violation of the dependency rule&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Response&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emailOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EmailInvalidError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
      Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Email&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; email &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emailOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isLeft&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;emailOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; passwordOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Either&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InsecurePasswordError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
      Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Password&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Password&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;passwordOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isLeft&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;passwordOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;userByUsername&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; userByEmail&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUserByUsername&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;username&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUserByEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; usernameTaken &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;userByUsername &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; accountCreated &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;userByEmail &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;usernameTaken&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;UsernameTakenError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;username&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;accountCreated&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;EmailInvalidError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AppError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UnexpectedError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The blaring problem is that the infrastructure layer is &lt;strong&gt;above&lt;/strong&gt; the &lt;strong&gt;application layer&lt;/strong&gt;. It would be a &lt;u&gt;violation of the dependency rule&lt;/u&gt; to mention the name of anything in the infrastructure layer.&lt;/p&gt;
&lt;p&gt;The way we fix that is &lt;a href=&quot;/articles/tutorials/dependency-injection-inversion-explained/&quot;&gt;dependency inversion&lt;/a&gt; of course.&lt;/p&gt;
&lt;p&gt;Instead of the use case relying directly on the &lt;code class=&quot;language-text&quot;&gt;UserRepo&lt;/code&gt; from the &lt;strong&gt;infrastructure layer&lt;/strong&gt;, we can put an &lt;u&gt;interface&lt;/u&gt; (depending on the methodology, people call this different things like port, abstraction) inbetween the two. &lt;/p&gt;
&lt;p&gt;That changes the dependency relationship from this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/wiki/dependency-rule/dr-violation.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;To this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/wiki/dependency-rule/dr-fixed.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;We&apos;ve just unbroke the Dependency Rule violation that was there a second ago.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;&lt;b&gt;Ports and Adapters&lt;/b&gt;: This is a huge part of the &quot;Ports &amp; Adapters&quot; methodology. Thinking this way means that there&apos;s another layer in between the application and infrastructure layer called the &lt;b&gt;Adapter Layer&lt;/b&gt;. The Adapter Layer contains only ports (interfaces) that specifies for the &lt;b&gt;Infrastructure Layer&lt;/b&gt;, &lt;i&gt;how&lt;/i&gt; to create an adapter for the port, and specifies to the &lt;b&gt;Application Layer&lt;/b&gt;, &lt;i&gt;what to expect&lt;/i&gt; from an implementation of that port. &lt;br/&gt;&lt;br/&gt;This kind of design is &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;SOLID&lt;/a&gt; and enables us to respect the Object-Oriented Design principle stating to &quot;always program to an abstraction, not a &lt;a href=&quot;/wiki/concrete-class/&quot;&gt;concretion&lt;/a&gt;.&quot;&lt;/p&gt;
&lt;h3 id=&quot;Infrastructure-Layer&quot; style=&quot;position:relative;&quot;&gt;Infrastructure Layer&lt;a href=&quot;#Infrastructure-Layer&quot; aria-label=&quot;Infrastructure Layer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The infrastructure layer, which primarily contains implementations of &lt;strong&gt;adapters&lt;/strong&gt; to things like &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;repositories&lt;/a&gt;, &lt;strong&gt;controllers&lt;/strong&gt;, and &lt;strong&gt;integrations to services&lt;/strong&gt; (like external APIs, Stripe, etc), can depend on &lt;em&gt;any&lt;/em&gt; other layer below it.&lt;/p&gt;
&lt;p&gt;For example, a &lt;strong&gt;controller&lt;/strong&gt; (infra) will usually rely on a specific &lt;strong&gt;use case&lt;/strong&gt; from the &lt;strong&gt;application layer&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; useCase&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CreateUserUseCase&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;useCase&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CreateUserUseCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;useCase &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; useCase&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeImpl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;useCase
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isLeft&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; error &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UsernameTakenError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;conflict&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EmailInvalidError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clientError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountAlreadyExistsError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;conflict&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; CreateUserError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InsecurePasswordError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clientError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
    
    &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&apos;s totally valid and follows the Dependency Rule.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Handling Collections in Aggregates (0-to-Many, Many-to-Many) - Domain-Driven Design w/ TypeScript]]></title><description><![CDATA[The aggregate design article I wrote was definitely my most in-depth article yet. And that's because it's such a big topic. In response to…]]></description><link>https://khalilstemmler.com/articles/typescript-domain-driven-design/one-to-many-performance/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/typescript-domain-driven-design/one-to-many-performance/</guid><pubDate>Thu, 25 Jul 2019 16:04:10 GMT</pubDate><content:encoded>&lt;p&gt;The &lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;aggregate design&lt;/a&gt; article I wrote was definitely my most in-depth article yet. And that&apos;s because it&apos;s such a big topic.&lt;/p&gt;
&lt;p&gt;In response to the article, I was asked a really good question about &lt;strong&gt;performance on collections&lt;/strong&gt;. Check it out:&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;
&quot;I would like ask a question regarding the Artist-Genres (1-m) relationship. &lt;br/&gt;&lt;br/&gt;In your example you limit the number of Genres an artist can have, but what do you if there is no such limit?&lt;br/&gt;&lt;br/&gt;
Do you load all related Genres when initializing a new Artist entity? 
&lt;br/&gt;&lt;br/&gt;
Let&apos;s say there is a Post-Comment (1-m) relation where a Post can have hundreds or even thousands of Comments. When you have a getPost useCase, do you also load all Comments?&quot;
&lt;br/&gt;&lt;br/&gt;
How do we handle when a collection will grow out of scope?&quot;
&lt;/p&gt;
&lt;p&gt;Really good question and a valid concern. Let&apos;s get into it.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Let&apos;s visualize the &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Comment&lt;/code&gt; classes.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// WatchedList is a custom utility I made that &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// encapsulates a collection/array. It&apos;s able to&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// tell when items are initial vs. newly added.&lt;/span&gt;
  comments&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; WatchedList&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Comment&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Post&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PostProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;comments&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Comment&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;comments&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;currentItems&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So by this design, there are actually 0-to-many &lt;code class=&quot;language-text&quot;&gt;Comments&lt;/code&gt; for a &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt; with no domain logic restricting an upper bound.&lt;/p&gt;
&lt;p&gt;If everytime we want to &lt;em&gt;perform an operation on a post&lt;/em&gt;, we have to retrieve every &lt;code class=&quot;language-text&quot;&gt;Comment&lt;/code&gt; for it, our system simply won&apos;t scale.&lt;/p&gt;
&lt;p&gt;How do we remedy this?&lt;/p&gt;
&lt;h2 id=&quot;CQS-Command-Query-Segregation&quot; style=&quot;position:relative;&quot;&gt;CQS (Command Query Segregation)&lt;a href=&quot;#CQS-Command-Query-Segregation&quot; aria-label=&quot;CQS Command Query Segregation permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When we first start learning about DDD, we often run into terms like CQS, CQRS and Event Sourcing.&lt;/p&gt;
&lt;p&gt;These topics can explode into complexity for developers just getting started with DDD,  so I&apos;m going to attempt to keep it as pragmatic as possible for relatively simple DDD projects (that might be contradictory - DDD is needed when our projects are complex 🤪).&lt;/p&gt;
&lt;p&gt;Here&apos;s what&apos;s important for you to know now: CQS (command query segregation).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://martinfowler.com/bliki/CommandQuerySeparation.html&quot;&gt;Fowler&apos;s&lt;/a&gt; explanation is  that &quot;we should divide an object&apos;s methods into two sharply separated categories:&quot;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Queries: Return a result and do not change the observable state of the system (are free of side effects).&lt;/li&gt;
&lt;li&gt;Commands: Change the state of a system but do not return a value.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&apos;s talk about commands first.&lt;/p&gt;
&lt;h3 id=&quot;Commands&quot; style=&quot;position:relative;&quot;&gt;Commands&lt;a href=&quot;#Commands&quot; aria-label=&quot;Commands permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If we think about how we design our web applications, this is pretty much how we think of things when we do &lt;code class=&quot;language-text&quot;&gt;CRUD&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;With respect to things that web developers are concerned about, here are some &lt;strong&gt;command-like&lt;/strong&gt; equivalent terms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CRUD: &lt;code class=&quot;language-text&quot;&gt;Create&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Update&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Delete&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;HTTP REST Methods: &lt;code class=&quot;language-text&quot;&gt;POST&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;PUT&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;DELETE&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;PATCH&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Our &lt;code class=&quot;language-text&quot;&gt;Blog&lt;/code&gt; subdomain use cases: &lt;code class=&quot;language-text&quot;&gt;CreatePost&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;UpdatePost&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;DeletePost&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;PostComment&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;UpdateComment&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are &lt;strong&gt;writes&lt;/strong&gt;. Writes make changes to the system in some way.&lt;/p&gt;
&lt;p&gt;To illustrate, let&apos;s build the &lt;code class=&quot;language-text&quot;&gt;PostComment&lt;/code&gt; use case.&lt;/p&gt;
&lt;h3 id=&quot;PostComment-Use-Case---Command&quot; style=&quot;position:relative;&quot;&gt;PostComment Use Case - Command&lt;a href=&quot;#PostComment-Use-Case---Command&quot; aria-label=&quot;PostComment Use Case   Command permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostCommentRequestDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  postId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  html&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostCommentUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PostCommentRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; postRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IPostRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;postRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IPostRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; postRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostCommentRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; postId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; html &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Retrive the post&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; post&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Post &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findPostByPostId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;postId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Create a comment&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; commentOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Comment&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Comment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
        postId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
        userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        html
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;commentOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;commentOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Get the comment from the result&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comment&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Comment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; commentOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Add a comment&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// =&gt; This adds the comment to the post&apos;s watched list&lt;/span&gt;
      post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addComment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;comment&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And &lt;code class=&quot;language-text&quot;&gt;addComment(comment: Comment): void&lt;/code&gt; from within &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  comments&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; WatchedList&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Comment&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Post&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PostProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;comments&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Comment&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;comments&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;currentItems&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addComment&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;comment&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Comment&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Adds to comments: WatchedList&amp;lt;Comment&gt;.newItems()&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;comments&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;comment&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the code above,  we&apos;ve created a &lt;code class=&quot;language-text&quot;&gt;PostCommentUseCase&lt;/code&gt; where we retrieve the &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt;  domain entity from the repo, and &lt;strong&gt;utilized the &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt; domain&lt;/strong&gt; model to post a comment with &lt;code class=&quot;language-text&quot;&gt;post.addComment(comment)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&apos;s stop right there for a sec...&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When we retrieved the &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt; domain model, did we also retrieve all (possibly hundreds of) comments? &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;No.&lt;/p&gt;
&lt;p&gt;Why not?&lt;/p&gt;
&lt;p&gt;Well, we &lt;em&gt;could&lt;/em&gt; set a &lt;code class=&quot;language-text&quot;&gt;limit&lt;/code&gt; on the number of &lt;code class=&quot;language-text&quot;&gt;Comments&lt;/code&gt; we return initially from our repo.&lt;/p&gt;
&lt;p&gt;For example, our &lt;code class=&quot;language-text&quot;&gt;baseQuery()&lt;/code&gt; method in the &lt;code class=&quot;language-text&quot;&gt;PostRepo&lt;/code&gt; could look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IPostRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createBaseQuery&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; models &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      include&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
          model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Comment&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
          &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Comment&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
          limit&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
          order&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;date_posted&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;DESC&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This would have the effect of returning the &lt;strong&gt;5 most recent comments&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;But don&apos;t we have to return all of the &lt;code class=&quot;language-text&quot;&gt;Comments&lt;/code&gt; in this &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt;? Doesn&apos;t that ruin our &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt; domain model? &lt;/p&gt;
&lt;p&gt;No, it doesn&apos;t. &lt;/p&gt;
&lt;p&gt;My question is, for this &lt;code class=&quot;language-text&quot;&gt;PostCommentUseCase&lt;/code&gt; (which we&apos;ve identified as a &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt;), did we &lt;em&gt;need&lt;/em&gt; to have all the comments in order to execute it?&lt;/p&gt;
&lt;p&gt;Is there some invariant that we need to enforce here on the comments in the list to post a new comment? &lt;/p&gt;
&lt;p&gt;In the &lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;previous article&lt;/a&gt;, we looked at the fact that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;...an &quot;aggregate&quot; is a cluster of associated objects that we treat as a unit for the purpose of data changes.&quot; - Evans. 126&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And in Vaughn Vernon&apos;s book, he says that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;...“When trying to discover the Aggregates, we must understand the model’s true invariants. Only with that knowledge can we determine which objects should be clustered into a given Aggregate. An invariant is a business rule that must always be consistent.” - Excerpt From: Vernon, Vaughn. “Implementing Domain-Driven Design.” &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Emphasis on &lt;strong&gt;true invariants&lt;/strong&gt;. Understand that there &lt;em&gt;aren&apos;t any reasons&lt;/em&gt; for us to need to have all of child &lt;code class=&quot;language-text&quot;&gt;Posts&lt;/code&gt; in order to execute this &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Unless there was a rule to limit the &lt;strong&gt;total number of comments allowed&lt;/strong&gt; to have been posted, and unlike my &lt;code class=&quot;language-text&quot;&gt;Genres&lt;/code&gt; example in the previous article, if the upper bound was much higher (say, 6000), then we might consider making &lt;code class=&quot;language-text&quot;&gt;totalComments: number&lt;/code&gt; a required member of the &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt; entity upon retrieval from the &lt;code class=&quot;language-text&quot;&gt;PostRepo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A &lt;code class=&quot;language-text&quot;&gt;COUNT(*) WHERE post_id = &amp;quot;$&amp;quot;&lt;/code&gt; would be much more efficient than having to retrive and reconsistute 6000 comments in memory &lt;em&gt;in order to post&lt;/em&gt; a &lt;code class=&quot;language-text&quot;&gt;comment&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;So let’s continue, I just pulled in &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt; and did &lt;code class=&quot;language-text&quot;&gt;post.addComment(comment)&lt;/code&gt;. Next, we&apos;ll save it to the repo.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostCommentUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PostCommentRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostCommentRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; postId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; html &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
      post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addComment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;comment&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// save the post, cascading the save the&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// any commentsRepos as well for new comments&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When I do &lt;code class=&quot;language-text&quot;&gt;postRepo.save(post)&lt;/code&gt;, it’ll pass any new &lt;code class=&quot;language-text&quot;&gt;comments&lt;/code&gt; in the &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt; model to the &lt;code class=&quot;language-text&quot;&gt;commentRepo&lt;/code&gt; and save them like we did &lt;a href=&quot;/articles/typescript-domain-driven-design/aggregate-design-persistence/&quot;&gt;last time&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nice.&lt;/p&gt;
&lt;p&gt;Let’s flip it around to some &lt;code class=&quot;language-text&quot;&gt;READ&lt;/code&gt;s now.&lt;/p&gt;
&lt;h3 id=&quot;Reads&quot; style=&quot;position:relative;&quot;&gt;Reads&lt;a href=&quot;#Reads&quot; aria-label=&quot;Reads permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&apos;s say that I&apos;m working on creating the API call to return the &lt;code class=&quot;language-text&quot;&gt;Post&lt;/code&gt; as a resource.&lt;/p&gt;
&lt;h4 id=&quot;Getting-a-Post-by-Id&quot; style=&quot;position:relative;&quot;&gt;Getting a Post by Id&lt;a href=&quot;#Getting-a-Post-by-Id&quot; aria-label=&quot;Getting a Post by Id permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The API call might look like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GET &lt;code class=&quot;language-text&quot;&gt;/post/:id&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And the &lt;code class=&quot;language-text&quot;&gt;GetPostByIdUseCase&lt;/code&gt; simply retrives that post.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GetPostByIdRequestDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  postId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GetPostByIdResponseDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  post&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Post&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GetPostByIdUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GetPostByIdRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GetPostByIdResponseDTO&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; postRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IPostRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;postRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IPostRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; postRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GetPostByIdRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; postId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Retrive the post&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; post&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Post &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;postRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findPostByPostId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;postId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Return it&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GetPostByIdResponseDTO&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And the &lt;code class=&quot;language-text&quot;&gt;PostRepo&lt;/code&gt; only returns the 5 most recent &lt;code class=&quot;language-text&quot;&gt;Comments&lt;/code&gt; in the post &lt;strong&gt;by default&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IPostRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createBaseQuery&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; models &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      include&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
          model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Comment&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
          &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Comment&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
          limit&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
          order&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;date_posted&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;DESC&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findPostByPostId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;postId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostId &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Post&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; PostModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Post&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; query &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createBaseQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    query&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;where&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;post_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      postId &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PostId&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;postId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; postId
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; post &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; PostModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; PostMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That should be enough for the first call. And you could even tune that if you like.&lt;/p&gt;
&lt;p&gt;What about retrieving the rest of the resource? Namely, the &lt;code class=&quot;language-text&quot;&gt;Comments&lt;/code&gt;. &lt;/p&gt;
&lt;h3 id=&quot;Getting-a-Post-Comments-By-Post-Id&quot; style=&quot;position:relative;&quot;&gt;Getting a Post Comments By Post Id&lt;a href=&quot;#Getting-a-Post-Comments-By-Post-Id&quot; aria-label=&quot;Getting a Post Comments By Post Id permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Assume I&apos;m reading the post via the UI and I start to scroll down. What happens if this post has over 1000 comments. What do we do now?&lt;/p&gt;
&lt;p&gt;If we had some slick fetch-on-scroll functionality, we could make some async API calls on-scroll.&lt;/p&gt;
&lt;p&gt;To fetch more comments, the API call might look like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GET /post/:id/comments?offset=5&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We could create a &lt;code class=&quot;language-text&quot;&gt;GetCommentsByPostId&lt;/code&gt; use case.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GetCommentsByPostIdRequestDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  postId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  offset&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GetCommentsByIdResponseDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  comments&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Comment&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GetCommentsByPostIdUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GetCommentsByPostIdRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GetCommentsByIdResponseDTO&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; commentsRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ICommentsRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;commentsRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ICommentsRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;commentsRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; commentsRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GetCommentsByPostIdRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; postId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; offset &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Retrive the comments&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comments&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Comment&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;commentsRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findCommentsByPostId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;postId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; offset&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Return it&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GetPostByIdResponseDTO&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        comments
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CommentsRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ICommentsRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createBaseQuery&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; models &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      limit&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findCommentsByPostId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;postId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostId &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; offset&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Comment&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; CommentModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Comment&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; query &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createBaseQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    query&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;where&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;post_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      postId &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PostId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PostId&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;postId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; postId
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    query&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;offset &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; offset &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; offset &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comments &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; CommentModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; comments&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; CommentMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While we still use our reference to the &lt;code class=&quot;language-text&quot;&gt;post&lt;/code&gt; through &lt;code class=&quot;language-text&quot;&gt;postId&lt;/code&gt;, we go straight to the &lt;code class=&quot;language-text&quot;&gt;comments&lt;/code&gt; repository to get what we need for this query.&lt;/p&gt;
&lt;h3 id=&quot;Forum-conversation-about-leaving-out-the-Aggregate-for-querying&quot; style=&quot;position:relative;&quot;&gt;Forum conversation about leaving out the Aggregate for querying&lt;a href=&quot;#Forum-conversation-about-leaving-out-the-Aggregate-for-querying&quot; aria-label=&quot;Forum conversation about leaving out the Aggregate for querying permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;From &lt;a href=&quot;https://softwareengineering.stackexchange.com/questions/47488/are-ddd-aggregates-really-a-good-idea-in-a-web-application&quot;&gt;StackExchange&lt;/a&gt;,&lt;/p&gt;
&lt;p&gt;&quot;Don&apos;t use your Domain Model and aggregates for querying.&lt;/p&gt;
&lt;p&gt;In fact, what you are asking is a common enough question that a set of principles and patterns has been established to avoid just that. It is called CQRS.&quot;&lt;/p&gt;
&lt;p&gt;&quot;I can&apos;t imagine that anyone would advocate returning entire aggregates of information when you don&apos;t need it.&quot; I&apos;m trying to say that you are exactly correct with this statement. Do not retrieve an entire aggregate of information when you do not need it. This is the very core of CQRS applied to DDD. You don&apos;t need an aggregate to query. Get the data through a different mechanism (a repo works nicely), and then do that consistently.&quot;&lt;/p&gt;
&lt;h3 id=&quot;Takeaway&quot; style=&quot;position:relative;&quot;&gt;Takeaway&lt;a href=&quot;#Takeaway&quot; aria-label=&quot;Takeaway permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;If there&apos;s a invariant / business rule that needs to be protected by returning all of the elements in an associated collection under an aggregate boundary, return them all (like the case with &lt;code class=&quot;language-text&quot;&gt;Genres&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;If there&apos;s &lt;strong&gt;no underlying invariant / business rule to protect&lt;/strong&gt; by returning all unbounded elements in an associated collection under an aggregate boundary, don&apos;t bother returning them all for &lt;code class=&quot;language-text&quot;&gt;COMMANDS&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Execute &lt;code class=&quot;language-text&quot;&gt;QUERY&lt;/code&gt;s directly against the repos (or consider looking into how to build Read Models). &lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;Additional-reading&quot; style=&quot;position:relative;&quot;&gt;Additional reading&lt;a href=&quot;#Additional-reading&quot; aria-label=&quot;Additional reading permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://softwareengineering.stackexchange.com/questions/47488/are-ddd-aggregates-really-a-good-idea-in-a-web-application&quot;&gt;https://softwareengineering.stackexchange.com/questions/47488/are-ddd-aggregates-really-a-good-idea-in-a-web-application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20150118024058/http://cre8ivethought.com/blog/2009/11/12/cqrs--la-greg-young&quot;&gt;https://web.archive.org/web/20150118024058/http://cre8ivethought.com/blog/2009/11/12/cqrs--la-greg-young&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;“Rule: Model True Invariants in Consistency Boundaries” (Vaughn  Vernon, Chapter 10 Aggregates)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.dotnetcurry.com/patterns-practices/1461/command-query-separation-cqs&quot;&gt;https://www.dotnetcurry.com/patterns-practices/1461/command-query-separation-cqs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Challenges in Aggregate Design #1 - Domain-Driven Design w/ TypeScript]]></title><description><![CDATA[Here's a question I got recently, Q: How can a domain model reference a model from a different subdomain? The person who asked the question…]]></description><link>https://khalilstemmler.com/articles/typescript-domain-driven-design/domain-modeling-1/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/typescript-domain-driven-design/domain-modeling-1/</guid><pubDate>Thu, 25 Jul 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Here&apos;s a question I got recently,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Q: How can a domain model reference a model from a different subdomain?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The person who asked the question also gave me a few details about their actual problem.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Order.create(userId) creates an order, which is only accepted if User.getReputation() is &quot;trusted&quot;. A user&apos;s reputation is trusted if more than 10 products were shipped, otherwise it returns failure result.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;OK, let&apos;s dive in.&lt;/p&gt;
&lt;p&gt;I&apos;m going to assume we&apos;re working on some sort of ecommerce platform containing a &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt; subdomain and a &lt;code class=&quot;language-text&quot;&gt;Shipping&lt;/code&gt; one.  &lt;/p&gt;
&lt;h2 id=&quot;User-subdomain&quot; style=&quot;position:relative;&quot;&gt;User subdomain&lt;a href=&quot;#User-subdomain&quot; aria-label=&quot;User subdomain permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt; subdomain, let&apos;s assume we have an aggregate root for &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserEmail&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  password&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserPassword&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; guardResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;againstNullOrUndefinedBulk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; arguementName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;email&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; arguementName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;password&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;guardResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;guardResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I was thinking about the &lt;code class=&quot;language-text&quot;&gt;user.getReputation()&lt;/code&gt; method. Does it make sense for that to be on the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; entity?&lt;/p&gt;
&lt;p&gt;Is &lt;code class=&quot;language-text&quot;&gt;reputation&lt;/code&gt; even a concern in the &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt; subdomain?&lt;/p&gt;
&lt;p&gt;I personally don&apos;t think so.&lt;/p&gt;
&lt;p&gt;Here&apos;s why.&lt;/p&gt;
&lt;h3 id=&quot;Aggregate-Boundaries&quot; style=&quot;position:relative;&quot;&gt;Aggregate Boundaries&lt;a href=&quot;#Aggregate-Boundaries&quot; aria-label=&quot;Aggregate Boundaries permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In Vaughn Vernon&apos;s DDD Book, he says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“When trying to discover the Aggregates in a Bounded Context, we must understand the model’s true invariants. Only with that knowledge can we determine which objects should be clustered into a given Aggregate.” - Excerpt From: Vernon, Vaughn. “Implementing Domain-Driven Design.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think there&apos;s a slight confusion as to which entity the responsibility of calculating &lt;code class=&quot;language-text&quot;&gt;reputation&lt;/code&gt; belongs to.&lt;/p&gt;
&lt;p&gt;It&apos;s our natural instinct to assume that everything is the responsibility of &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;, because &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt; are primarily how we think about people using our systems.&lt;/p&gt;
&lt;p&gt;But in DDD, we have to think a little more granularly. Especially if there are several subdomains.&lt;/p&gt;
&lt;p&gt;In the example given, &lt;code class=&quot;language-text&quot;&gt;reputation&lt;/code&gt; is apparently calculated from the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; aggregate. However, the calculation can only be determined by counting the number of &quot;products shipped&quot;.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Products&lt;/code&gt; are not within the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; &lt;strong&gt;aggregate&apos;s consistency boundary&lt;/strong&gt;. The &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; entity doesn&apos;t contain a reference to the collection of &lt;code class=&quot;language-text&quot;&gt;products&lt;/code&gt;. And it shouldn&apos;t need  to.&lt;/p&gt;
&lt;h3 id=&quot;Determine-responsibility-by-assigning-use-cases-to-subdomains&quot; style=&quot;position:relative;&quot;&gt;Determine responsibility by assigning use cases to subdomains&lt;a href=&quot;#Determine-responsibility-by-assigning-use-cases-to-subdomains&quot; aria-label=&quot;Determine responsibility by assigning use cases to subdomains permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Remember from the section titled &quot;&lt;strong&gt;We discover use cases through conversation&lt;/strong&gt;&quot; from &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;this article&lt;/a&gt; where we discovered that the &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt; subdomain is only responsible for &lt;strong&gt;Identity &amp;#x26; Access Management&lt;/strong&gt; and contains &lt;strong&gt;use cases like&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;login(userEmail: UserEmail, password: UserPassword)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;logout(authToken: JWTToken)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;verifyEmail(emailVerificationToken: EmailVerificationToken)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;changePassword(passwordResetToken: Token, password: UserPassword)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think what we&apos;re missing is a &lt;code class=&quot;language-text&quot;&gt;Merchant&lt;/code&gt; aggregate in the &lt;code class=&quot;language-text&quot;&gt;Shipping&lt;/code&gt; subdomain like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; ReputationType &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;unranked&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;poor&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;good&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;great&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MerchantProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  products&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; WatchedList&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Product&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  shippedProducts&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; WatchedList&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Product&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  reputation&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ReputationType&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Merchant&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;MerchantProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;From this subdomain, I would expect to see more use cases like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;shipProduct(product: Product)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;getMerchantById(merchantId: MerchantId)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Calculating-Merchant-reputation&quot; style=&quot;position:relative;&quot;&gt;Calculating &lt;code class=&quot;language-text&quot;&gt;Merchant&lt;/code&gt; reputation&lt;a href=&quot;#Calculating-Merchant-reputation&quot; aria-label=&quot;Calculating Merchant reputation permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;That solves the problem of us trying to figure out how to refer to an entity from a separate subdomain (which we usually do with application services / use cases in correct cases).&lt;/p&gt;
&lt;p&gt;But now, how do we calculate &lt;code class=&quot;language-text&quot;&gt;ReputationType&lt;/code&gt;? &lt;/p&gt;
&lt;p&gt;At first glance, the obvious approach would be to tally up all of the products shipped like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Merchant&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;MerchantProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getReputation&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ReputationType &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; numProductsShipped &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; products&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getItems&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;curr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; product&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shipped &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; curr &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; curr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipped &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;unranked&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipped &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// etc and so on.&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But since &lt;code class=&quot;language-text&quot;&gt;Merchant&lt;/code&gt; has a 0-to-many relationship with &lt;code class=&quot;language-text&quot;&gt;Product&lt;/code&gt;, that unbounded relationship could end up spanning hundreds or thousands of &lt;code class=&quot;language-text&quot;&gt;products&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That would mean we would have to ensure we retrieve all products from the repo when we retrieve a &lt;code class=&quot;language-text&quot;&gt;Merchant&lt;/code&gt;... always.&lt;/p&gt;
&lt;p&gt;Not ideal.&lt;/p&gt;
&lt;p&gt;Here&apos;s a better approach.&lt;/p&gt;
&lt;h2 id=&quot;Updating-Reputation-after-every-ProductShippedEvent-domain-event&quot; style=&quot;position:relative;&quot;&gt;Updating &lt;code class=&quot;language-text&quot;&gt;Reputation&lt;/code&gt; after every &lt;code class=&quot;language-text&quot;&gt;ProductShippedEvent&lt;/code&gt; domain event&lt;a href=&quot;#Updating-Reputation-after-every-ProductShippedEvent-domain-event&quot; aria-label=&quot;Updating Reputation after every ProductShippedEvent domain event permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since &lt;code class=&quot;language-text&quot;&gt;Product&lt;/code&gt; is under the consistency boundary of &lt;code class=&quot;language-text&quot;&gt;Merchant&lt;/code&gt;, we could add a method to &lt;code class=&quot;language-text&quot;&gt;Merchant&lt;/code&gt; to mark a &lt;code class=&quot;language-text&quot;&gt;product&lt;/code&gt; as shipped.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Merchant&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;MerchantProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;shipProduct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// Add the item to shipped products so that the &lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Product repo can save it as updated when we&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// persist the domain entity. &lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shippedProducts&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Create a domain event for the product shipment&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDomainEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProductShippedEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then, from the same subdomain, we could subscribe to the Domain Event.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/modules/shipping/subscribers&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AfterProductShippedEvent&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IHandle&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ProductShippedEvent&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; merchantRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IMerchantRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; productRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IProductRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;merchantRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IMerchantRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IProductRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;merchantRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; merchantRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;productRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; productRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    DomainEvents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;onProductShippedEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ProductShippedEvent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;onProductShippedEvent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ProductShippedEvent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; numberShippedProducts&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;productRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;countNumberShippedProducts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;merchantId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// Use a domain service to calculate the reputation.&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// We want to ensure that we encapsulate as much domain logic&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// in the domain layer as possible.&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; newMerchantReputation&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ReputationType &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; MerchantReputationService
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;calculateReputation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;numberShippedProducts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Set the reputation&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;merchantRepo
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setMerchantReputation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;product&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;merchantId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; newMerchantReputation&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is what we call &lt;strong&gt;eventual consistency&lt;/strong&gt; and it&apos;s within the realm of topics related to but not constrained to &lt;a href=&quot;https://martinfowler.com/bliki/CQRS.html&quot;&gt;CQRS&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to Design & Persist Aggregates - Domain-Driven Design w/ TypeScript]]></title><description><![CDATA[Can it be that it was all so simple then? Remember when our apps were simple? Remember we could make CRUD API calls to our backend to change…]]></description><link>https://khalilstemmler.com/articles/typescript-domain-driven-design/aggregate-design-persistence/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/typescript-domain-driven-design/aggregate-design-persistence/</guid><pubDate>Wed, 24 Jul 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;special-quote&quot;&gt;Translated by readers to: &lt;a target=&quot;_blank&quot; href=&quot;https://qiita.com/ROPITAL/items/2298abf06b92914ee35b&quot;&gt;Japanese (日本語)&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Can it be that it was all so simple then?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Remember when our apps were simple? Remember we could make CRUD API calls to our backend to change the state of the application? We were able to do that simply by using our Sequelize or Mongoose ORM models directly from our controllers. &lt;/p&gt;
&lt;p&gt;Those were the good ol&apos; days.&lt;/p&gt;
&lt;p&gt;Look at us now. We&apos;re writing code that is pretty much a &lt;strong&gt;software implementation&lt;/strong&gt; of the business. We&apos;re using Object-Oriented Programming principles to create &lt;strong&gt;rich domain models&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;The rules and concepts that exist in the business in &lt;em&gt;real life&lt;/em&gt; are now showing up in our code as &lt;a href=&quot;/articles/typescript-domain-driven-design/entities/&quot;&gt;entities&lt;/a&gt; and &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;value objects&lt;/a&gt;. We&apos;re using &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt; to express what all the different &lt;strong&gt;actors&lt;/strong&gt; (groups of users) in our system can do from within their respective subdomains.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We&apos;re modeling software to solve &lt;strong&gt;complex real life business problems&lt;/strong&gt;. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;The-challenge&quot; style=&quot;position:relative;&quot;&gt;The challenge&lt;a href=&quot;#The-challenge&quot; aria-label=&quot;The challenge permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A common recurring theme in software is &lt;strong&gt;relationships&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;A large part of programming (especially Object-Oriented Programming) is about relationships. By decomposing gargantuan problems into smaller classes and modules, we&apos;re able to tackle small pieces of that complexity in bite-sized chunks.&lt;/p&gt;
&lt;p&gt;This decomposition is what we&apos;ve been doing with &lt;strong&gt;value objects&lt;/strong&gt; to &lt;u&gt;encapsulate validation logic&lt;/u&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GenreNameProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * @class GenreName
 * @description The genre name class is a Value Object that encapsulates
 * the validation logic required to specify the name of a Genre.
 * @see Genre entity
 */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GenreName&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ValueObject&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GenreNameProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;constuctor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GenreNameProps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GenreName&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; guardResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;againstNullOrUndefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;guardResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GenreName&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;guardResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GenreName&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Name must be greater than 2 chars and less than 100.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GenreName&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; name &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;Instead of just using a &quot;string&quot;, we use a GenreName class to encapsulate the validation logic that a Genre&apos;s name must be between 2 and 100 characters.&lt;/p&gt;
&lt;p&gt;And we use &lt;strong&gt;entities&lt;/strong&gt; to enforce model invariants, further decomposing the larger problem itself. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ArtistProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Artist&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Entity&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ArtistProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MAX_NUMBER_OF_GENRES_PER_ARTIST&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ArtistProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Artist &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;genres&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;/**
   * @method addGenre
   * @desc Notice this class encapsulates an important business rule about
   * the 1-many relationship between Artist and Genre. We can only add
   * a certain number of Genres to Artist.
   */&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;addGenre&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;genre&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; Artist&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MAX_NUMBER_OF_GENRES_PER_ARTIST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Max number of genres reached&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;genreAlreadyExists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;genre&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;genre&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;Invariant/business rule: An artist can only have at most 5 genres.&lt;/p&gt;
&lt;p&gt;As we define rules and constraints about how our isolated &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;Domain Layer&lt;/a&gt; entities are allowed to relate to each other (1-to-1, 1-to-many, many-to-many), and which operations are valid at which times, several questions are introduced:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How do we (cascade and) save this cluster of entities to the database?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;How do we decide on boundaries for all these entities in the cluster?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Do I need a repository for each of these entities?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In this article, I&apos;ll show you how we use &lt;strong&gt;Aggregates&lt;/strong&gt; to create a boundary around a cluster of entities that we treat as a singular unit. I&apos;ll also show you how to persist them to a database.&lt;/p&gt;
&lt;h2 id=&quot;a-classanchor-nameAggregatesaWhat-is-an-Aggregate&quot; style=&quot;position:relative;&quot;&gt;&lt;a class=&quot;anchor&quot; name=&quot;Aggregates&quot;&gt;&lt;/a&gt;What is an Aggregate?&lt;a href=&quot;#a-classanchor-nameAggregatesaWhat-is-an-Aggregate&quot; aria-label=&quot;a classanchor nameAggregatesaWhat is an Aggregate permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The best definition of an aggregate comes from Eric Evans and his &lt;a href=&quot;https://amzn.to/2K3B4og&quot;&gt;DDD book&lt;/a&gt;; in it, he says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An &quot;aggregate&quot; is a cluster of associated objects that we treat as a unit for the purpose of data changes.&quot; - Evans. 126&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let&apos;s break that apart a bit. &lt;/p&gt;
&lt;p&gt;An actual &lt;em&gt;aggregate&lt;/em&gt; itself is the &lt;strong&gt;entire clump of objects&lt;/strong&gt; that are connected together.&lt;/p&gt;
&lt;p&gt;Take the following (semi) complete &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; class from &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;White Label&lt;/a&gt; - or see all the code &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AggregateRoot &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../core/domain/AggregateRoot&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../core/domain/UniqueEntityID&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Result &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../core/Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Artist &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./artist&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; TraderId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../trading/domain/traderId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Guard &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../core/Guard&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; VinylId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./vinylId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; VinylNotes &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./vinylNotes&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Album &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./album&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  traderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TraderId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  album&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Album&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  vinylNotes&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; VinylNotes&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  dateAdded&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; VinylCollection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;VinylProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;vinylId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; VinylId &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; VinylId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;artist&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Artist &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;album&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Album &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dateAdded&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Date &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dateAdded&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;traderId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TraderId &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;traderId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;vinylNotes&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; VinylNotes &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylNotes&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; VinylProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; VinylProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; propsResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;againstNullOrUndefinedBulk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;album&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;artist&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;traderId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;traderId&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;propsResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;succeeded&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;propsResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinyl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      dateAdded&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dateAdded &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dateAdded &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isNewlyCreated &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isNewlyCreated&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// TODO: Dispatch domain events &lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In White Label, &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; is posted by the &lt;code class=&quot;language-text&quot;&gt;Trader&lt;/code&gt; that owns it. &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; has a relationship to an &lt;code class=&quot;language-text&quot;&gt;Artist&lt;/code&gt; and a &lt;code class=&quot;language-text&quot;&gt;Album&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That means &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; has 3 different relationships to other entities.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; belongs to (1-1) a &lt;code class=&quot;language-text&quot;&gt;Trader&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; has a (1-1) &lt;code class=&quot;language-text&quot;&gt;Artist&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; belongs to (1-1) an &lt;code class=&quot;language-text&quot;&gt;Album&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Album&lt;/code&gt; has many (1-m) &lt;code class=&quot;language-text&quot;&gt;Genres&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Artist&lt;/code&gt; has many (1-m) &lt;code class=&quot;language-text&quot;&gt;Genres&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This relationship puts &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; in the middle and makes &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; the main entity in this clump: the &lt;strong&gt;aggregate root&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-aggregates/aggregate-clump.svg&quot; alt=&quot;Vinyl Aggregate - Domain-Driven Design TypeScript DDD&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An &lt;strong&gt;Aggregate&lt;/strong&gt; is the clump of related entities to treat as a unit for data changes.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Aggregate Root&lt;/strong&gt; is the main entity that holds references to the other ones. It&apos;s the only entity in the clump that is used for direct lookup.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hopefully, you&apos;re still with me and we have a better understanding of what &lt;strong&gt;aggregates&lt;/strong&gt; actually &lt;em&gt;are&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;We still have to talk about the &lt;strong&gt;second&lt;/strong&gt; part of Evans&apos; description about aggregates; particularly the part where he says that &quot;we treat [them] as a unit for the purpose of data changes&quot;.&lt;/p&gt;
&lt;h2 id=&quot;a-classanchor-nameBoundariesaFiguring-out-boundaries&quot; style=&quot;position:relative;&quot;&gt;&lt;a class=&quot;anchor&quot; name=&quot;Boundaries&quot;&gt;&lt;/a&gt;Figuring out boundaries&lt;a href=&quot;#a-classanchor-nameBoundariesaFiguring-out-boundaries&quot; aria-label=&quot;a classanchor nameBoundariesaFiguring out boundaries permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What&apos;s Evans talking about when he says we treat aggregates as a unit &lt;u&gt;for data changes&lt;/u&gt;?&lt;/p&gt;
&lt;p&gt;What are the data changes we&apos;re talking about?&lt;/p&gt;
&lt;p&gt;Particularly the &lt;code class=&quot;language-text&quot;&gt;CREATE&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;DELETE&lt;/code&gt;, or &lt;code class=&quot;language-text&quot;&gt;UPDATE&lt;/code&gt;-like operations. We want to make sure that we don&apos;t allow anything illegal to the domain to leave a domain model corrupted.&lt;/p&gt;
&lt;p&gt;OK, and where do these &lt;em&gt;data changes&lt;/em&gt; originate?&lt;/p&gt;
&lt;p&gt;Data changes originate from the &lt;strong&gt;use cases&lt;/strong&gt; our application fulfils. You know, the features. The app&apos;s &lt;em&gt;entire reason&lt;/em&gt; for &lt;strong&gt;being&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Take White Label again. We&apos;ve identified the majority of the use cases today for the &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; entity (which we&apos;ve determined is actually an Aggregate Root). &lt;/p&gt;
&lt;p&gt;Some of the use cases &lt;em&gt;make data changes&lt;/em&gt; (command) to the database, and some of them simply &lt;code class=&quot;language-text&quot;&gt;READ&lt;/code&gt; (query) from the database.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Catalog&lt;/code&gt; Use cases on Vinyl in my personal catalog&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;addVinyl&lt;/code&gt;: add new existing vinyl&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;createNewVinyl&lt;/code&gt;: create new vinyl&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;getRecommendations&lt;/code&gt;: get recommendations based on vinyl currently in catalog&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;getAllVinyl&lt;/code&gt;: get all vinyl in catalog&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;getVinylByVinylId&lt;/code&gt;: get particular vinyl in catalog&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;removeVinyl&lt;/code&gt;: remove particular vinyl in catalog&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;searchCatalogForVinyl&lt;/code&gt;: search for vinyl in catalog&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;updateVinyl&lt;/code&gt;: update vinyl in catalog&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Marketplace&lt;/code&gt; Use cases on Vinyl in the public marketplace&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;searchMarketplaceForVinyl&lt;/code&gt;: search the marketplace for vinyl&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;getRecommendationsByVinylId&lt;/code&gt;: get recommendations based on other users that have this vinyl&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Great, we know the use cases for &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt;. Now what?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We can design the aggregate such that it enables all of the (command-like) use cases to be executed, while protecting any model invariants.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ahh. And therein lies the trickiness. &lt;/p&gt;
&lt;p&gt;And therein also lies our &lt;u&gt;ability to determine aggregate boundaries&lt;/u&gt;. &lt;strong&gt;That&apos;s the goal&lt;/strong&gt; in aggregate design.&lt;/p&gt;
&lt;p&gt;We define the boundaries such a way that all of &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt;&apos;s &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt; use cases can be performed, and enough information is provided within the boundary to ensure that that no operation breaks any business rules.&lt;/p&gt;
&lt;p&gt;However, it turns out that that&apos;s not always the easiest thing to get right the very first time. &lt;/p&gt;
&lt;p&gt;Sometimes new business rules are introduced.&lt;/p&gt;
&lt;p&gt;Sometimes new use cases are added.&lt;/p&gt;
&lt;p&gt;Quite often, we end up being a bit off and have to make changes to our aggregate boundaries.&lt;/p&gt;
&lt;p&gt;There are countless other essays, documents, books, resources, etc on effective aggregate design, and that&apos;s because it&apos;s so tricky to get right. There&apos;s a lot to consider.&lt;/p&gt;
&lt;h2 id=&quot;a--classanchor-nameDesign-ConsiderationsaThings-to-consider-in-aggregate-design&quot; style=&quot;position:relative;&quot;&gt;&lt;a  class=&quot;anchor&quot; name=&quot;Design-Considerations&quot;&gt;&lt;/a&gt;Things to consider in aggregate design&lt;a href=&quot;#a--classanchor-nameDesign-ConsiderationsaThings-to-consider-in-aggregate-design&quot; aria-label=&quot;a  classanchor nameDesign ConsiderationsaThings to consider in aggregate design permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If our goals in designing aggregates are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Provide enough info to enforce model invariants within a boundary&lt;/li&gt;
&lt;li&gt;Execute use cases&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then we also have to consider what we might be doing to the database and our transactions in making overly large aggregate boundaries.&lt;/p&gt;
&lt;h3 id=&quot;Database--Transaction-Performance&quot; style=&quot;position:relative;&quot;&gt;Database / Transaction Performance&lt;a href=&quot;#Database--Transaction-Performance&quot; aria-label=&quot;Database  Transaction Performance permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-aggregates/aggregate-design-tradeoffs.svg&quot; alt=&quot;Domain-Driven Design Aggregate Design Trade Offs - DDD TypeScript&quot;&gt;&lt;/p&gt;
&lt;p&gt;At this point with our boundaries on &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt;, think about how many tables we need to join in order to retrieve a single &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-aggregates/aggregate-db.svg&quot; alt=&quot;Domain-Driven Design Aggregate Database View - DDD TypeScript&quot;&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s add another goal to our aggregate design list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Provide enough info to enforce model invariants within a boundary&lt;/li&gt;
&lt;li&gt;Execute use cases&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ensure decent database performance&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;DTOs&quot; style=&quot;position:relative;&quot;&gt;DTOs&lt;a href=&quot;#DTOs&quot; aria-label=&quot;DTOs permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There&apos;s also the case of DTOs. Quite often, we need to map a &lt;strong&gt;Domain entity&lt;/strong&gt; to a &lt;strong&gt;DTO / View Model&lt;/strong&gt; to return to the user.&lt;/p&gt;
&lt;p&gt;In this case of &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; in White Label, we might need to return something like looks like this to the user:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-aggregates/WhiteLabelAddVinyl8.svg&quot; alt=&quot;White Label - Domain Driven Design TypeScript DDD App - Wireframe #8&quot;&gt;&lt;/p&gt;
&lt;p&gt;There&apos;s the actual &lt;code class=&quot;language-text&quot;&gt;ArtistName&lt;/code&gt;, the artwork, the &lt;code class=&quot;language-text&quot;&gt;year&lt;/code&gt; it was released and more.&lt;/p&gt;
&lt;p&gt;Our DTO might need to look like the following in order to build this view on the frontend.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GenreDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  genre_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ArtistDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  artist_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  artist_image&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  genres&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GenreDTO&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AlbumDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  yearReleased&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  artwork&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  genres&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GenreDTO&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  vinyl_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  trader_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ArtistDTO&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  album&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AlbumDTO&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That realization might really force us ensure we include the entire &lt;code class=&quot;language-text&quot;&gt;Artist&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Album&lt;/code&gt; entities inside the aggregate boundary for &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; because it &lt;em&gt;might make it easier&lt;/em&gt; for us to build API response DTOs.&lt;/p&gt;
&lt;p&gt;That gives us another goal in aggregate design:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Provide enough info to enforce model invariants within a boundary&lt;/li&gt;
&lt;li&gt;Execute use cases&lt;/li&gt;
&lt;li&gt;Ensure decent database performance&lt;/li&gt;
&lt;li&gt;(optional, not recommended though) &lt;strong&gt;Provide enough info to transform a Domain Entity to a DTO&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The reason why this is an &lt;strong&gt;optional&lt;/strong&gt; goal stems from the CQS (Command-Query Segregation) Principle.&lt;/p&gt;
&lt;h3 id=&quot;Command-Query-Segregation&quot; style=&quot;position:relative;&quot;&gt;Command-Query Segregation&lt;a href=&quot;#Command-Query-Segregation&quot; aria-label=&quot;Command Query Segregation permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;CQS says that any operation is either a &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt; or a &lt;code class=&quot;language-text&quot;&gt;QUERY&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;So if a function performs a &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt;, it has no return value (&lt;code class=&quot;language-text&quot;&gt;void&lt;/code&gt;), like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Valid&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createVinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// create and save&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Valid&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;updateVinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// update&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Invalid&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;updateVinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// update&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When we make changes to our aggregates (&lt;code class=&quot;language-text&quot;&gt;UPDATE&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;DELETE&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;CREATE&lt;/code&gt;), we&apos;re performing &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;In this scenario, we &lt;em&gt;need to have a complete aggregate&lt;/em&gt; pulled into memory in order to enforce any invariant rules before approving the &lt;code class=&quot;language-text&quot;&gt;COMMAND&lt;/code&gt; or rejecting it because some business rule isn&apos;t being satisfied.&lt;/p&gt;
&lt;p&gt;OK. Makes sense. &lt;/p&gt;
&lt;p&gt;But queries are different. &lt;code class=&quot;language-text&quot;&gt;QUERIES&lt;/code&gt; simply &lt;strong&gt;return a value&lt;/strong&gt; but also produce &lt;strong&gt;absolutely no side-effects&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Valid&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getVinylById&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// returns vinyl&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Invalid&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getVinylById&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinyl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getVinyl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;updateVinyl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// bad, side-effect of a QUERY&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// returns vinyl&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So in the context of DTOs, adding additional info to our aggregate for the sake of having them available for our DTOs has potential to hurt performance, don&apos;t do it.&lt;/p&gt;
&lt;p&gt;DTOs can have a tight requirement to fulfill a user inferface, so instead of filling up an aggregate with all that info, just retrieve the data you need, directly from the repository/repositories to create the DTO.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Hopefully you&apos;re understanding that aggregate design takes a little bit of work. &lt;/p&gt;
&lt;p&gt;Like most things in software development, there&apos;s no free lunch. You have to consider the tradeoffs in simplicity vs. performance. &lt;/p&gt;
&lt;p&gt;I&apos;ll always recommend to start with simplicity and then address performance later if necessary.&lt;/p&gt;
&lt;h2 id=&quot;a-classanchor-nameExample-ProblemaAdd-Vinyl-Use-Case&quot; style=&quot;position:relative;&quot;&gt;&lt;a class=&quot;anchor&quot; name=&quot;Example-Problem&quot;&gt;&lt;/a&gt;&quot;Add Vinyl&quot; Use Case&lt;a href=&quot;#a-classanchor-nameExample-ProblemaAdd-Vinyl-Use-Case&quot; aria-label=&quot;a classanchor nameExample ProblemaAdd Vinyl Use Case permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To get the hang of designing aggregates and persisting them, let&apos;s walk through building something. &lt;/p&gt;
&lt;p&gt;I&apos;m currently working on a &lt;a href=&quot;https://essentialist.dev&quot;&gt;Domain Driven Design w/ TypeScript Course&lt;/a&gt; where we build a &lt;strong&gt;Vinyl Trading application&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;You can check out the code for the project here on &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;One of the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt; is to be able to &lt;u&gt;add vinyl that you currently have in your collection at home&lt;/u&gt; so that you can then make trades and receive offers on them. &lt;/p&gt;
&lt;h3 id=&quot;The-flow&quot; style=&quot;position:relative;&quot;&gt;The flow&lt;a href=&quot;#The-flow&quot; aria-label=&quot;The flow permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Starting from an empty page, we&apos;re presented with the ability to &lt;strong&gt;Add Vinyl&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-aggregates/WhiteLabelAddVinyl1.svg&quot; alt=&quot;White Label - Domain Driven Design TypeScript DDD App - Wireframe #1&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Empty collection page.&lt;/p&gt;
&lt;p&gt;When we click on &lt;strong&gt;&quot;Add Vinyl&quot;&lt;/strong&gt;, we can fill out a form starting with the &lt;code class=&quot;language-text&quot;&gt;Artist&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If the &lt;code class=&quot;language-text&quot;&gt;Artist&lt;/code&gt; isn&apos;t currently in our system, then the user will need to &lt;strong&gt;Create a new artist&lt;/strong&gt; as well.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-aggregates/WhiteLabelAddVinyl2.svg&quot; alt=&quot;White Label - Domain Driven Design TypeScript DDD App - Wireframe #2&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Add new vinyl - Enter the artist, no auto-suggest&lt;/p&gt;
&lt;p&gt;Clicking &lt;strong&gt;&quot;+ Create new artist [Artist name]&quot;&lt;/strong&gt; will open up more details for the user to fill out like the &lt;code class=&quot;language-text&quot;&gt;Genres&lt;/code&gt; of this artist.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-aggregates/WhiteLabelAddVinyl3.svg&quot; alt=&quot;White Label - Domain Driven Design TypeScript DDD App - Wireframe #3&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Add new vinyl - Fill in addition New Artist details&lt;/p&gt;
&lt;p&gt;When they&apos;re completed with that, they can add the &lt;code class=&quot;language-text&quot;&gt;Album&lt;/code&gt; details.  &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-aggregates/WhiteLabelAddVinyl4.svg&quot; alt=&quot;White Label - Domain Driven Design TypeScript DDD App - Wireframe #4&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Add new vinyl - Add new album.&lt;/p&gt;
&lt;p&gt;Again, if the album hasn&apos;t ever been added to the platform, they&apos;ll be required to fill in all the details manually.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-aggregates/WhiteLabelAddVinyl6.svg&quot; alt=&quot;White Label - Domain Driven Design TypeScript DDD App - Wireframe #6&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Add new vinyl - Fill in album details.&lt;/p&gt;
&lt;p&gt;Lastly, they can add any relevant information about their copy of the record before hitting submit.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-aggregates/WhiteLabelAddVinyl7.svg&quot; alt=&quot;White Label - Domain Driven Design TypeScript DDD App - Wireframe #7&quot;&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;Add new vinyl - Submission&lt;/p&gt;
&lt;p&gt;And then it should show up on their dashboard. The album artwork can be retrieved from a &lt;a href=&quot;https://github.com/stemmlerjs/music-metadata&quot;&gt;music metadata API&lt;/a&gt; and then ammended to the &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; through an application service in the backend that listens for a &lt;code class=&quot;language-text&quot;&gt;VinylCreatedEvent&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-aggregates/WhiteLabelAddVinyl8.svg&quot; alt=&quot;White Label - Domain Driven Design TypeScript DDD App - Wireframe #8&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-classanchor-nameSolutionaDeveloping-the-Use-Case&quot; style=&quot;position:relative;&quot;&gt;&lt;a class=&quot;anchor&quot; name=&quot;Solution&quot;&gt;&lt;/a&gt;Developing the Use Case&lt;a href=&quot;#a-classanchor-nameSolutionaDeveloping-the-Use-Case&quot; aria-label=&quot;a classanchor nameSolutionaDeveloping the Use Case permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since we&apos;re sure that &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; is going to be our Aggregate Root, let&apos;s talk about what we need in the &lt;code class=&quot;language-text&quot;&gt;AggregateRoot&lt;/code&gt; class.&lt;/p&gt;
&lt;h3 id=&quot;Our-basic-Aggregate-Root-class&quot; style=&quot;position:relative;&quot;&gt;Our basic Aggregate Root class&lt;a href=&quot;#Our-basic-Aggregate-Root-class&quot; aria-label=&quot;Our basic Aggregate Root class permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;First off, an Aggregate Root is still an &lt;code class=&quot;language-text&quot;&gt;Entity&lt;/code&gt;, so let&apos;s simply extend our existing &lt;code class=&quot;language-text&quot;&gt;Entity&amp;lt;T&amp;gt;&lt;/code&gt; class.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Entity &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./Entity&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./UniqueEntityID&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Entity&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What else should an aggregate root class be responsible for?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Dispatching &lt;strong&gt;Domain Events&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;We won&apos;t get into it now, but in a future article you&apos;ll see how we can apply the &lt;strong&gt;observer pattern&lt;/strong&gt; in order to signal when relevant things happen, directly from domain layer itself.&lt;/p&gt;
&lt;p&gt;But for now, this is good enough to simply give the class name intent.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AggregateRoot &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../core/domain/AggregateRoot&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;VinylProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;special-quote&quot;&gt;If you wanna skip ahead and see what this class will look like when we hook up domain events, feel free to check out the code &lt;a href=&quot;https://github.com/stemmlerjs/white-label/blob/master/src/core/domain/AggregateRoot.ts&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now let&apos;s get to the Use Case.&lt;/p&gt;
&lt;h3 id=&quot;The-Add-Vinyl-To-Catalog-Use-Case&quot; style=&quot;position:relative;&quot;&gt;The Add Vinyl To Catalog Use Case&lt;a href=&quot;#The-Add-Vinyl-To-Catalog-Use-Case&quot; aria-label=&quot;The Add Vinyl To Catalog Use Case permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&apos;s think about the general algorithm here:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Given a request DTO containing:
  - the current user&amp;#39;s id
  - the vinyl details containing:
    - artist details
      - artist id if it already existed
      - name and genres if it didn&amp;#39;t 
    - album details
      - albumId if it already existed
      - name, year and genres if it didn&amp;#39;t exist
    - where each genre also contains:
      - the genre id if it already existed
      - the genre name if it didn&amp;#39;t already exist

We want to:
  - Find or create the artist 
  - Find or create the album
  - Create the new vinyl (artist, album, traderId)
  - Save the new vinyl &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Looks good, let&apos;s start with the request DTOs. What do we need from the API call?&lt;/p&gt;
&lt;h4 id=&quot;Request-DTOs&quot; style=&quot;position:relative;&quot;&gt;Request DTOs&lt;a href=&quot;#Request-DTOs&quot; aria-label=&quot;Request DTOs permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;For this API call to account for situations where the &lt;code class=&quot;language-text&quot;&gt;Genres&lt;/code&gt; exist and when they don&apos;t exist, we&apos;ll split a &lt;code class=&quot;language-text&quot;&gt;GenresRequestDTO&lt;/code&gt; into two parts.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GenresRequestDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  ids&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here&apos;s the breakdown of this approach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;new: string[]&lt;/code&gt; contains text values of new genres&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;ids: string[]&lt;/code&gt; contains the ids of the genres that we want to link.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since &lt;code class=&quot;language-text&quot;&gt;Album&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Artist&lt;/code&gt; both take &lt;code class=&quot;language-text&quot;&gt;Genres&lt;/code&gt;, we&apos;ll give them each their own key in the main payload.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddVinylToCatalogUseCaseRequestDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  artistNameOrId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  artistGenres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; GenresRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  albumNameOrId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  albumGenres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; GenresRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  albumYearReleased&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  traderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You&apos;ll also notice that we&apos;ve named the &lt;code class=&quot;language-text&quot;&gt;Artist&lt;/code&gt; name and the &lt;code class=&quot;language-text&quot;&gt;Album&lt;/code&gt; name as &lt;code class=&quot;language-text&quot;&gt;[albumName/artistName]orId&lt;/code&gt;. That&apos;s because if the &lt;code class=&quot;language-text&quot;&gt;Album&lt;/code&gt; already exists, we can just include the id. Same for &lt;code class=&quot;language-text&quot;&gt;Artist&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now let&apos;s hook these all up to an &lt;code class=&quot;language-text&quot;&gt;AddVinylToCatalogUseCase&lt;/code&gt; like we&apos;ve done in our &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;previous articles on creating use cases&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;Creating-the-AddVinylToCatalogUseCase-class&quot; style=&quot;position:relative;&quot;&gt;Creating the &lt;code class=&quot;language-text&quot;&gt;AddVinylToCatalogUseCase&lt;/code&gt; class&lt;a href=&quot;#Creating-the-AddVinylToCatalogUseCase-class&quot; aria-label=&quot;Creating the AddVinylToCatalogUseCase class permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Lots of imports&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UseCase &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../core/domain/UseCase&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Vinyl &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/vinyl&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IVinylRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../repos/vinylRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Result &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../core/Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; TextUtil &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../utils/TextUtil&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IArtistRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../repos/artistRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Artist &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/artist&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; TraderId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../trading/domain/traderId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../core/domain/UniqueEntityID&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ArtistName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/artistName&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ParseUtils &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../utils/ParseUtils&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; GenresRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; IGenresRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../repos/genresRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Genre &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/genre&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Album &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/album&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IAlbumRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../repos/albumRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; GenreId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/genreId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GenresRequestDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  ids&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddVinylToCatalogUseCaseRequestDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  artistNameOrId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  artistGenres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; GenresRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  albumNameOrId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  albumGenres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; GenresRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  albumYearReleased&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  traderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddVinylToCatalogUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;AddVinylToCatalogUseCaseRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; vinylRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; artistRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IArtistRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; albumRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IAlbumRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; genresRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IGenresRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Make sure to dependency inject repos that we&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// need, only referring to their interface. Never&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// their concrete class.&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token parameter&quot;&gt;vinylRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    artistRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IArtistRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    genresRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GenresRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    albumRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IAlbumRepo&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; vinylRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; artistRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genresRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; genresRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;albumRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; albumRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getGenresFromDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;artistGenres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// TODO: &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getArtist&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AddVinylToCatalogUseCaseRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Artist&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// TODO: &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getAlbum&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AddVinylToCatalogUseCaseRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Artist&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Album&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// TODO: &lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AddVinylToCatalogUseCaseRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; traderId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; album&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Album&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Get the artist &lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; artistOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getArtist&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        artist &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; artistOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Get the album&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; albumOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAlbum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; artist&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;albumOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;albumOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        album &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; albumOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Create vinyl&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinylOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        album&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; album&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; artist&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        traderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TraderId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;traderId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinyl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; vinylOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Save the vinyl&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// This is where all the magic happens&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At this point, you can see the general shape of the algorithm we defined earlier.&lt;/p&gt;
&lt;p&gt;Our goal with this Use Case is to retrieve everything necessary to create a &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; in memory, and then pass it to the &lt;code class=&quot;language-text&quot;&gt;VinylRepo&lt;/code&gt; to cascade everything that needs to be saved.&lt;/p&gt;
&lt;p&gt;All that&apos;s left to do in this class is to fill in the blanks for how we retrieve everything.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;Also, let me remind you that you can view the entire source code &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Take a look. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UseCase &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../core/domain/UseCase&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Vinyl &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/vinyl&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IVinylRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../repos/vinylRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Result &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../core/Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; TextUtil &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../utils/TextUtil&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IArtistRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../repos/artistRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Artist &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/artist&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; TraderId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../trading/domain/traderId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../core/domain/UniqueEntityID&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ArtistName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/artistName&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ParseUtils &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../utils/ParseUtils&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; GenresRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; IGenresRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../repos/genresRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Genre &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/genre&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Album &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/album&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IAlbumRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../repos/albumRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; GenreId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../domain/genreId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GenresRequestDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  ids&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddVinylToCatalogUseCaseRequestDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  artistNameOrId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  artistGenres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; GenresRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  albumNameOrId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  albumGenres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; GenresRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  albumYearReleased&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  traderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddVinylToCatalogUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;AddVinylToCatalogUseCaseRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; vinylRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; artistRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IArtistRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; albumRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IAlbumRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; genresRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IGenresRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token parameter&quot;&gt;vinylRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    artistRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IArtistRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    genresRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GenresRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    albumRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IAlbumRepo&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; vinylRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; artistRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genresRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; genresRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;albumRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; albumRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getGenresFromDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;artistGenres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genresRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findByIds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ParseUtils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parseObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistGenres&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GenresRequestDTO&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ids  
          &lt;span class=&quot;token comment&quot;&gt;// existing ids, we&apos;re converting them into genreIds so&lt;/span&gt;
          &lt;span class=&quot;token comment&quot;&gt;// that we can pass them into genresRepo.findByIds(genreIds: GenreId[])&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;genreId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; GenreId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;genreId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;//  Join both groups of ids together. New and old.&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ParseUtils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parseObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistGenres&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GenresRequestDTO&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// new genres.. let&apos;s create &apos;em&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getArtist&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AddVinylToCatalogUseCaseRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Artist&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; artistNameOrId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; artistGenres &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isArtistIdProvided &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TextUtil&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isUUID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistNameOrId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isArtistIdProvided&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; artist &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findByArtistId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistNameOrId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; found &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;found&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Artist&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Artist&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Couldn&apos;t find artist by id=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;artistNameOrId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Artist&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
        name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ArtistName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistNameOrId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
        genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getGenresFromDTO&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistGenres &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getAlbum&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AddVinylToCatalogUseCaseRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Artist&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Album&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; albumNameOrId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; albumGenres&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; albumYearReleased &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isAlbumIdProvided &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TextUtil&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isUUID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;albumNameOrId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isAlbumIdProvided&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; album &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;albumRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findAlbumByAlbumId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;albumNameOrId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; found &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;found&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Album&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Album&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Couldn&apos;t find album by id=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;album&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Album&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; albumNameOrId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        artistId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; artist&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getGenresFromDTO&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;albumGenres &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        yearReleased&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; albumYearReleased
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AddVinylToCatalogUseCaseRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; traderId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; album&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Album&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; artistOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getArtist&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        artist &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; artistOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; albumOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAlbum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; artist&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;albumOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;albumOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        album &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; albumOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinylOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        album&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; album&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; artist&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        traderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TraderId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;traderId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
  
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinyl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; vinylOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// This is where all the magic happens&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You&apos;ve made it pretty far in this article. Let&apos;s recap what we&apos;ve done so far in the use case and what&apos;s next. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We&apos;ve created a DTO that enables us to use existing or new genres, albums, and artists to create vinyl.&lt;/li&gt;
&lt;li&gt;We&apos;ve written code that will pull in all the resources necessary to create a vinyl (album, artist, traderId).&lt;/li&gt;
&lt;li&gt;Next, we have to persist it by looking at the &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; aggregate and passing parts of it to the correct repositories. &lt;/li&gt;
&lt;li&gt;A repository will &lt;code class=&quot;language-text&quot;&gt;save()&lt;/code&gt; our aggregate and manage cascading the rest of the complex persistence code.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Persisting-an-aggregate&quot; style=&quot;position:relative;&quot;&gt;Persisting an aggregate&lt;a href=&quot;#Persisting-an-aggregate&quot; aria-label=&quot;Persisting an aggregate permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Ready to finish it off?&lt;/p&gt;
&lt;p&gt;Let&apos;s see how we can persist this aggregate.&lt;/p&gt;
&lt;p&gt;Take a look at the &lt;code class=&quot;language-text&quot;&gt;VinylRepo&lt;/code&gt; class&apos;, particularly the &lt;code class=&quot;language-text&quot;&gt;save()&lt;/code&gt; method.&lt;/p&gt;
&lt;h4 id=&quot;VinylRepo-saves-vinyl&quot; style=&quot;position:relative;&quot;&gt;VinylRepo (saves vinyl)&lt;a href=&quot;#VinylRepo-saves-vinyl&quot; aria-label=&quot;VinylRepo saves vinyl permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Repo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../core/infra/Repo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Vinyl &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../domain/vinyl&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; VinylId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../domain/vinylId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; VinylMap &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../mappers/VinylMap&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; TraderId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../trading/domain/traderId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IArtistRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./artistRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IAlbumRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./albumRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IVinylRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Repo&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getVinylById&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; VinylId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getVinylCollection&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;traderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IVinylRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; models&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; albumRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IAlbumRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; artistRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IArtistRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;models&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; artistRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IArtistRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; albumRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IAlbumRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; artistRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;albumRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; albumRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createBaseQuery&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; models &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      include&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
          model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Artist&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Artist&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          include&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Genre&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ArtistGenres&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; required&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
          model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Album&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Album&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
          include&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Genre&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;AlbumGenres&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; required&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; 
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getVinylById&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; VinylId &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; VinylModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; query &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createBaseQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    query&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;where&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;vinyl_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      vinylId &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;VinylId&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;vinylId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinylId
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sequelizeVinylInstance &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; VinylModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;sequelizeVinylInstance &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; VinylMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sequelizeVinylInstance&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; VinylId &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; VinylModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; query &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createBaseQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    query&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;where&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;vinyl_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      vinylId &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;VinylId&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;vinylId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinylId
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sequelizeVinylInstance &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; VinylModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;sequelizeVinylInstance &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getVinylCollection&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;traderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TraderId &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; VinylModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; query &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createBaseQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    query&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;where&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;trader_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      traderId &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TraderId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TraderId&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;traderId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; traderId
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sequelizeVinylCollection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; VinylModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; sequelizeVinylCollection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; VinylMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rollbackSave&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;vinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; VinylModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeArtistById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;albumRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeAlbumById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; VinylModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;destroy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        vinyl_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; VinylModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; exists&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rawVinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; VinylMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toPersistence&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;albumRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;exists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; VinylModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rawVinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; VinylModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rawVinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;rollbackSave&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In &lt;code class=&quot;language-text&quot;&gt;VinylRepo&lt;/code&gt;, we have methods for retrieving &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; by id, checking for it&apos;s existence, and getting the entire collection for &lt;code class=&quot;language-text&quot;&gt;Trader&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&apos;s walk through the &lt;code class=&quot;language-text&quot;&gt;save()&lt;/code&gt; method.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IVinylRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// 1. Get access to the Sequelize ORM vinyl model. Our repo&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// simply encapsulates access to this.&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; VinylModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// 2. Check to see if the vinyl already exists or not.&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// If it exists, then we&apos;ll perform an UPDATE. If not,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// we perform a CREATE.&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; exists&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// 3. VinylMap create a JSON object that the Sequelize&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Vinyl model needs in order to save it to the DB.&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Check it out: &lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// https://github.com/stemmlerjs/white-label/blob/master/src/catalog/mappers/VinylMap.ts&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rawVinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; VinylMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toPersistence&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;VinylMap-changes-vinyl-to-different-formats&quot; style=&quot;position:relative;&quot;&gt;VinylMap (changes vinyl to different formats)&lt;a href=&quot;#VinylMap-changes-vinyl-to-different-formats&quot; aria-label=&quot;VinylMap changes vinyl to different formats permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Take a look at the &lt;code class=&quot;language-text&quot;&gt;VinylMap&lt;/code&gt;. This class is singularly responsible for performing transformations on the &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; class from the database all the way to DTO.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Mapper &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../core/infra/Mapper&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Vinyl &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../domain/vinyl&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../core/domain/UniqueEntityID&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ArtistMap &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./ArtistMap&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AlbumMap &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./AlbumMap&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; TraderId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../trading/domain/traderId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylMap&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Mapper&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinylOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      traderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TraderId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;trader_id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ArtistMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Artist&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      album&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AlbumMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Album&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinyl_id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    vinylOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylOrError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; vinylOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; vinylOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toPersistence&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      vinyl_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      artist_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      album_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      notes&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylNotes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; VinylDTO &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      vinyl_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      trader_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;traderId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tostring&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ArtistMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDTO&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      album&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AlbumMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDTO&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Back to the &lt;code class=&quot;language-text&quot;&gt;save()&lt;/code&gt; method in &lt;code class=&quot;language-text&quot;&gt;VinylRepo&lt;/code&gt;. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IVinylRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; VinylModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; exists&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rawVinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; VinylMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toPersistence&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// 4. Delegate saving an artist (if it doesn&apos;t exist) &lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// to the artistRepo. &lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// We know that we need to do this before we save Vinyl because&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// vinyl relies on it through the 1-to-1 relationship&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// 5. Also delegate saving the album (if it doesn&apos;t exist)&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// to the albumRepo class. Vinyl also relies on this to exist&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// first.&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;albumRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;exists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// 6. If vinyl doesn&apos;t yet exist, then we&apos;ll CREATE it.&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; VinylModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rawVinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// 7. If it does exist, then we&apos;ll UPDATE it.&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; VinylModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rawVinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// 8. If anything fails, we&apos;ll do a manual rollback.&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;rollbackSave&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can be sure that the &lt;code class=&quot;language-text&quot;&gt;AlbumRepo&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;ArtistRepo&lt;/code&gt; are following a similar algorithm to the one outlined here in &lt;code class=&quot;language-text&quot;&gt;VinylRepo&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&quot;AlbumRepo-delegated-the-responsibility-of-persisting-Albums&quot; style=&quot;position:relative;&quot;&gt;AlbumRepo (delegated the responsibility of persisting &lt;code class=&quot;language-text&quot;&gt;Albums&lt;/code&gt;)&lt;a href=&quot;#AlbumRepo-delegated-the-responsibility-of-persisting-Albums&quot; aria-label=&quot;AlbumRepo delegated the responsibility of persisting Albums permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;I&apos;ve included the entire file here in case you want to peruse, but pay attention to the &lt;code class=&quot;language-text&quot;&gt;save()&lt;/code&gt; method.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Repo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../core/infra/Repo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Album &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../domain/album&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AlbumId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../domain/albumId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AlbumMap &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../mappers/AlbumMap&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IGenresRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./genresRepo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Genre &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../domain/genre&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IAlbumRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Repo&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Album&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;findAlbumByAlbumId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;albumId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AlbumId &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Album&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;removeAlbumById&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;albumId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AlbumId &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Album&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AlbumRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IAlbumRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; models&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; genresRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IGenresRepo

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;models&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; genresRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IGenresRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genresRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; genresRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createBaseQuery&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; models &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      include&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Genre&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;AlbumGenres&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; required&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findAlbumByAlbumId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;albumId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AlbumId &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Album&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; AlbumModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Album&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; query &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createBaseQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    query&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;album_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      albumId &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AlbumId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;AlbumId&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;albumId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; albumId
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; album &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; AlbumModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;album &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; AlbumMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;albumId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AlbumId &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; AlbumModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Album&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; query &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createBaseQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    query&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;album_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      albumId &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AlbumId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;AlbumId&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;albumId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; albumId
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; album &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; AlbumModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;album &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;removeAlbumById&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;albumId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AlbumId &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Album&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; AlbumModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; AlbumModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;destroy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
      where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
        artist_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; albumId &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AlbumId&lt;/span&gt; 
          &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;AlbumId&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;albumId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
          &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; albumId
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rollbackSave&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;album&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Album&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; AlbumModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Album&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genresRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeByGenreIds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genreId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; AlbumModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;destroy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        album_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; album&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setAlbumGenres&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sequelizeAlbumModel&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;sequelizeAlbumModel &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; genres&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; sequelizeAlbumModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setGenres&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; d&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genreId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;album&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Album&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Album&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; AlbumModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Album&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; exists&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;albumId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rawAlbum&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; AlbumMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toPersistence&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; sequelizeAlbumModel&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genresRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;saveCollection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;exists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        sequelizeAlbumModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; AlbumModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rawAlbum&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        sequelizeAlbumModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; AlbumModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rawAlbum&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setAlbumGenres&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sequelizeAlbumModel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; album&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;rollbackSave&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; album&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The algorithm is pretty much the same with one small difference to how we save &lt;code class=&quot;language-text&quot;&gt;Album&lt;/code&gt; &lt;code class=&quot;language-text&quot;&gt;Genres&lt;/code&gt; with &lt;code class=&quot;language-text&quot;&gt;setAlbumGenres()&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&quot;Sequelize-Associations&quot; style=&quot;position:relative;&quot;&gt;Sequelize Associations&lt;a href=&quot;#Sequelize-Associations&quot; aria-label=&quot;Sequelize Associations permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;In Sequelize, we have the ability to &lt;a href=&quot;http://docs.sequelizejs.com/manual/associations.html&quot;&gt;set associations&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;When we define our models, we can do things like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;Album&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;belongsToMany&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Genre&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;AlbumGenres&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; through&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TagAlbumGenre&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; foreignKey&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;genre_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;belongsToMany&lt;/code&gt; association to &lt;code class=&quot;language-text&quot;&gt;Genres&lt;/code&gt; adds a &lt;code class=&quot;language-text&quot;&gt;setGenres()&lt;/code&gt; method to the sequelize &lt;code class=&quot;language-text&quot;&gt;Album&lt;/code&gt; instance, making it easier to set the current &lt;code class=&quot;language-text&quot;&gt;Genres&lt;/code&gt; for an  &lt;code class=&quot;language-text&quot;&gt;Album&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Rollbacks&quot; style=&quot;position:relative;&quot;&gt;Rollbacks&lt;a href=&quot;#Rollbacks&quot; aria-label=&quot;Rollbacks permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The last thing to talk about are rolling back transactions.&lt;/p&gt;
&lt;p&gt;Some C# popularized the &lt;a href=&quot;https://www.c-sharpcorner.com/UploadFile/b1df45/unit-of-work-in-repository-pattern/&quot;&gt;Unit Of Work&lt;/a&gt; pattern.&lt;/p&gt;
&lt;p&gt;However, for us to roll that ourselves would mean that we would have to pass a &lt;a href=&quot;http://docs.sequelizejs.com/manual/transactions.html&quot;&gt;sequelize transaction&lt;/a&gt; through all of our repos and tie the execution of our use case to a single database transaction.&lt;/p&gt;
&lt;p&gt;In theory, it sounds beautful. Implementing it is a little bit of a nightmare.&lt;/p&gt;
&lt;p&gt;I&apos;ve chosen to manually apply rollbacks because it&apos;s much simpler for now.&lt;/p&gt;
&lt;p&gt;For example, in &lt;code class=&quot;language-text&quot;&gt;AlbumRepo&lt;/code&gt;, this is what it looks like to rollback an &lt;code class=&quot;language-text&quot;&gt;Album&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AlbumRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IAlbumRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rollbackSave&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;album&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Album&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; AlbumModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Album&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genresRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeByGenreIds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genreId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; AlbumModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;destroy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        album_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; album&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I like to consider that a pretty pragmatic approach, although if it seems right for you, you could give Unit of Work a try.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;Takeaways&quot; style=&quot;position:relative;&quot;&gt;Takeaways&lt;a href=&quot;#Takeaways&quot; aria-label=&quot;Takeaways permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&apos;ll conclude this article here. If you stuck around this long, you&apos;re a real trooper you deserve all the success in domain modeling possible.&lt;/p&gt;
&lt;p&gt;To recap, here&apos;s what we covered;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Entities and value objects are clustered together into aggregates&lt;/li&gt;
&lt;li&gt;An &quot;aggregate&quot; is a cluster of associated objects that we treat as a unit for the purpose of data changes.&quot;&lt;/li&gt;
&lt;li&gt;The boundary is how far fully consistuted entities are in the aggregate.&lt;/li&gt;
&lt;li&gt;With all fully consistuted entities inside of the aggregate, it&apos;s possible for the aggregate root to enforce all invariants within the aggregate when it&apos;s state changes.&lt;/li&gt;
&lt;li&gt;An aggregate must always be returned fully constited from persistance. That constraint requires us to think hard about performance constraints and what&apos;s really necessary to fully pull from the database.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Our aggregate design goals are to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Provide enough info to enforce model invariants within a boundary&lt;/li&gt;
&lt;li&gt;Execute use cases&lt;/li&gt;
&lt;li&gt;Ensure decent database performance&lt;/li&gt;
&lt;li&gt;Provide enough info to transform a Domain Entity to a DTO&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Repositories are responsible for handling all of the complex aggregate persistence logic.&lt;/li&gt;
&lt;li&gt;Mappers are used to map aggregates to the format required for saving it in our persistence technology.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[There Is No Dominant Paradigm | Software Professionalism]]></title><description><![CDATA[If you ask a software consultant for advice on the best approach to anything, such as: what's the best framework to use what's the best ORM…]]></description><link>https://khalilstemmler.com/articles/software-professionalism/there-is-no-dominant-paradigm/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/software-professionalism/there-is-no-dominant-paradigm/</guid><pubDate>Thu, 11 Jul 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;If you ask a software consultant for advice on the &lt;strong&gt;best&lt;/strong&gt; approach to anything, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;what&apos;s the best framework to use&lt;/li&gt;
&lt;li&gt;what&apos;s the best ORM to use&lt;/li&gt;
&lt;li&gt;what&apos;s the cloud to deploy to&lt;/li&gt;
&lt;li&gt;what&apos;s the best way to split up this project?&lt;/li&gt;
&lt;li&gt;how SOLID should this code be?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;... a good consultant starts their reply with two words: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It depends...&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It&apos;s not uncommon to hear a lot of that when speaking with consultants because &lt;u&gt;professional people in software &lt;em&gt;rarely&lt;/em&gt; speak in absolutes&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;Software professionals recognize that there are tools and approaches which are optimal for certain tasks. The optimial tool for the task fully depends on &lt;strong&gt;context&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Context is everything in making decisions.&lt;/p&gt;
&lt;p&gt;Applied to the act of programming, depending on the context, we&apos;re either writing &lt;strong&gt;imperative&lt;/strong&gt; code, &lt;strong&gt;functional code&lt;/strong&gt; or &lt;strong&gt;object-oriented code&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Its how we write algorithms and detail, organize those details into methods, and structure the relationships between classes that contain the bulk of the work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Good software is all 3 paradigms at different times&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In this article, we&apos;ll cover the following:&lt;/p&gt;
&lt;ul class=&quot;aside&quot;&gt;
  &lt;li&gt;Primary characteristics of quality software&lt;/li&gt;
  &lt;li&gt;How good Imperative code reinforces reliable software&lt;/li&gt;
  &lt;li&gt;How good Functional code reinforces maintainable software&lt;/li&gt;
  &lt;li&gt;How good Object-Oriented code reinforces flexibile software&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;What-is-quality-software&quot; style=&quot;position:relative;&quot;&gt;What is quality software?&lt;a href=&quot;#What-is-quality-software&quot; aria-label=&quot;What is quality software permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A fair question. But it should be the basis for all of our development efforts.&lt;/p&gt;
&lt;p&gt;Quality software is software that ensures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;reliability&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;flexibility&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;maintainability&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Reliability&quot; style=&quot;position:relative;&quot;&gt;Reliability&lt;a href=&quot;#Reliability&quot; aria-label=&quot;Reliability permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Reliable software does what it was meant to do, always. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Submitting a comment&lt;/code&gt;: if I press ENTER to reply to a thread on a social networking site, it should save my comment, store it the db, perhaps also notify all people in the thread.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Making a purchase&lt;/code&gt;: if I enter my credit card and click submit, I expect it to charge me once and then send me a reciept.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Without considering the challenges of networking and deployment, writing the code to make things work once is easy. &lt;/p&gt;
&lt;p&gt;You can brute force /  imperatively / procedurally make anything work once, yes.&lt;/p&gt;
&lt;p&gt;But your job as a developer isn&apos;t over at that point though.&lt;/p&gt;
&lt;h3 id=&quot;Flexibility&quot; style=&quot;position:relative;&quot;&gt;Flexibility&lt;a href=&quot;#Flexibility&quot; aria-label=&quot;Flexibility permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There is one constant in software development: &lt;strong&gt;change&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Change will always occur. Features will always need to be added and adjusted.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Where does change come from?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We&apos;ve discovered that change requests always orignate from the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;actors/groups&lt;/a&gt; that own the feature.&lt;/p&gt;
&lt;p&gt;Therefore, it&apos;s in our &lt;strong&gt;best interest&lt;/strong&gt; to identify and structure our software around those those groups.&lt;/p&gt;
&lt;p&gt;This is why we:&lt;/p&gt;
&lt;p&gt;A: split our subdomains/components/modules based on &lt;a href=&quot;/wiki/conways-law/&quot;&gt;Conway&apos;s law&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A billing subdomain: &lt;code class=&quot;language-text&quot;&gt;Customer&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Subscriber&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Accountant&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Treasurer&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Employee&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A blogging subdomain: &lt;code class=&quot;language-text&quot;&gt;Editor&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Reviewer&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Guest&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Author&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A recruitment subdomain: &lt;code class=&quot;language-text&quot;&gt;JobSeeker&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Employer&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Interviewer&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Recruiter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Our vinyl-trading subdomain: &lt;code class=&quot;language-text&quot;&gt;Trader&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Admin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;An email marketing subdomain: &lt;code class=&quot;language-text&quot;&gt;Contact&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Recipient&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Sender&lt;/code&gt;,  &lt;code class=&quot;language-text&quot;&gt;ListOwner&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;B: Improve cohesion by locating &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases/features&lt;/a&gt; used by a particular group in the subdomain that they belong to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Our vinyl-trading subdomain use cases: &lt;code class=&quot;language-text&quot;&gt;addVinyl&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;makeOffer&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;acceptOffer&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;rejectOffer&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;C: Use polymorphism to &lt;a href=&quot;/wiki/dependency-inversion/&quot;&gt;flip the dependency graph&lt;/a&gt;, enabling architects to have full control over dependencies&lt;/p&gt;
&lt;p&gt;D: Use &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;Liskov Substitution&lt;/a&gt; to enable valid plugins to be decided upon at runtime&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If I need a &lt;strong&gt;mail&lt;/strong&gt; microservice, I can use either the &lt;code class=&quot;language-text&quot;&gt;MailChimpService&lt;/code&gt;, the &lt;code class=&quot;language-text&quot;&gt;SendGridService&lt;/code&gt;, the &lt;code class=&quot;language-text&quot;&gt;MailGunService&lt;/code&gt; or any other future mail microservice, as long as it&apos;s a &lt;code class=&quot;language-text&quot;&gt;Mailer&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Maintainability&quot; style=&quot;position:relative;&quot;&gt;Maintainability&lt;a href=&quot;#Maintainability&quot; aria-label=&quot;Maintainability permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Finally, since we&apos;ve confirmed that change is going to occur at some point, how do we &lt;strong&gt;limit the amount of time that it takes to take software from point &lt;em&gt;A&lt;/em&gt; to point &lt;em&gt;B&lt;/em&gt;&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;This is what we&apos;re primarily concerned about when we talk about &lt;strong&gt;maintainability&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;Is the code hard to understand? Are these functions &lt;a href=&quot;/articles/typescript-domain-driven-design/intention-revealing-interfaces/&quot;&gt;intention revealing&lt;/a&gt;? Are there modules that don&apos;t belong together? Will changing one thing break something else in a completely separate part of the application?&lt;/p&gt;
&lt;p&gt;By limiting side effects, separating concerns, and decoupling modules that don&apos;t belong together, we&apos;re improving the &lt;strong&gt;maintainability&lt;/strong&gt; of the code.&lt;/p&gt;
&lt;p&gt;Essentially, writing &lt;em&gt;clean code&lt;/em&gt; improves maintainability.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;We&apos;ve just discussed some of the most important software quality metrics. Others exist, but for application developers, I believe these are the most important.&lt;/p&gt;
&lt;p&gt;You&apos;ll discover next how each paradigm is &lt;strong&gt;best suited&lt;/strong&gt; to reinforce one of these software quality metrics.&lt;/p&gt;
&lt;h2 id=&quot;All-paradigms-are-necessary&quot; style=&quot;position:relative;&quot;&gt;All paradigms are necessary&lt;a href=&quot;#All-paradigms-are-necessary&quot; aria-label=&quot;All paradigms are necessary permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Recently, &lt;a href=&quot;https://twitter.com/unclebobmartin?lang=en&quot;&gt;Uncle Bob&lt;/a&gt; tweeted something meaningful out:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/professionalism/paradigm/paradigms.png&quot; alt=&quot;Uncle Bob on Imperative, Functional and Object-Oriented&quot;&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;via &lt;a href=&quot;https://twitter.com/unclebobmartin/status/1141726835794939906&quot;&gt;https://twitter.com/unclebobmartin/status/1141726835794939906&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Interesting statement. But, we should question everything. &lt;/p&gt;
&lt;p&gt;Someone else got there before I did.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/professionalism/paradigm/paradigms-response.png&quot; alt=&quot;Uncle Bob on Imperative, Functional and Object-Oriented&quot;&gt; &lt;/p&gt;
&lt;p&gt;Allow me to break this down a little bit. &lt;/p&gt;
&lt;p&gt;Here’s what Uncle Bob meant when he said that we “discovered [software is] three paradigms at different times”.&lt;/p&gt;
&lt;h3 id=&quot;Imperative-programming-reinforces-reliability&quot; style=&quot;position:relative;&quot;&gt;Imperative programming reinforces reliability&lt;a href=&quot;#Imperative-programming-reinforces-reliability&quot; aria-label=&quot;Imperative programming reinforces reliability permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/professionalism/paradigm/imperative.png&quot; alt=&quot;Imperative programming&quot;&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Imperative programming&lt;/strong&gt; is how we write our algorithms and procedures, storing data in variables and moving it around. This is where everyone starts out as new developers. It’s also where we focus a lot of our energy on naming variables well.&lt;/p&gt;
&lt;p&gt;This type of code is relatively easy to write and if we wanted, we could brute-force all of our problems in software writing imperative code.&lt;/p&gt;
&lt;p&gt;Sometimes that&apos;s the only option we have (if we&apos;re using languages like C).&lt;/p&gt;
&lt;p&gt;It&apos;s in our &lt;strong&gt;imperative&lt;/strong&gt; code that we focus on code at the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;detail level&lt;/a&gt; and ensure that we&apos;ve coded our algorithms. &lt;/p&gt;
&lt;p&gt;Ie: does it do what it was meant to do?&lt;/p&gt;
&lt;p&gt;Doing this well ensures &lt;code class=&quot;language-text&quot;&gt;reliability&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Functional-programming-reinforces-maintainability&quot; style=&quot;position:relative;&quot;&gt;Functional programming reinforces maintainability&lt;a href=&quot;#Functional-programming-reinforces-maintainability&quot; aria-label=&quot;Functional programming reinforces maintainability permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/professionalism/paradigm/functional.png&quot; alt=&quot;Functional programming&quot;&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Functional programming&lt;/strong&gt; is concerned with how we break those algorithms and procedures into functions. &lt;/p&gt;
&lt;p&gt;Now we get a little bit of code reusability and we can chain functionality together.&lt;/p&gt;
&lt;p&gt;No longer do we have to explicitly type everything out everytime we want to do something.&lt;/p&gt;
&lt;p&gt;This is powerful.&lt;/p&gt;
&lt;p&gt;This moves us towards &lt;a href=&quot;/articles/typescript-domain-driven-design/ddd-vs-crud-design/&quot;&gt;declarative programming&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Eventually we learn about good functional design principles, DRY, and doing one thing and doing it well; that latter of which is an &lt;strong&gt;alternative understanding of SRP&lt;/strong&gt; (not the &lt;em&gt;correct&lt;/em&gt; interpretation of SRP, that we talk about &lt;a href=&quot;/articles/solid-principles/single-responsibility/&quot;&gt;here&lt;/a&gt;).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For a lot of JavaScript developers, this is the asymptote that we constantly strive towards: to write side-effect free functions and reducing the need to rely on statefulness.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When we don&apos;t have to worry about side-effects, &lt;code class=&quot;language-text&quot;&gt;maintainability&lt;/code&gt; improves. &lt;/p&gt;
&lt;p&gt;We can be sure that when we&apos;re changing something, we&apos;re not going to break something else inadvertantly.&lt;/p&gt;
&lt;p&gt;When we&apos;re able to understand very clearly through intention revealing function names, expressive types, we can limit side effects by chaining complex logic in clear and maintainable ways:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;payload&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;genres&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addChange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setGenres&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; genresRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOrCreateGenresByName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ParseUtils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parseObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;payload&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GenresDTO&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; genresRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findGenresById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ParseUtils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parseObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;payload&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;GenresDTO&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ids
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For a lot of simple CRUD applications, we can get away with a lot &lt;em&gt;without&lt;/em&gt; even thinking about object-oriented programming or types.&lt;/p&gt;
&lt;p&gt;However, when our programs start to get sufficiently complex, we run into challenges.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;What do we mean by code getting &lt;em&gt;complex&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;Complex code is code where &lt;strong&gt;business logic starts to appear&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;At this point, without proper encapsulation, our app is just several procedural scripts. Fowler refers to this as a &lt;strong&gt;Transaction Script&lt;/strong&gt; &lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. &lt;/p&gt;
&lt;p&gt;Transaction Scripts are excellent for simple applications but the lack of encapsulation creates a breeding ground for code duplication.&lt;/p&gt;
&lt;p&gt;Code duplication leads to &lt;strong&gt;bugs&lt;/strong&gt; and an &lt;a href=&quot;/wiki/anemic-domain-model/&quot;&gt;anemic domain model&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It&apos;s at this moment exact moment when using a Domain Model (OOP) is preferred.&lt;/p&gt;
&lt;h3 id=&quot;Object-oriented-programming-reinforces-flexibility&quot; style=&quot;position:relative;&quot;&gt;Object-oriented programming reinforces flexibility&lt;a href=&quot;#Object-oriented-programming-reinforces-flexibility&quot; aria-label=&quot;Object oriented programming reinforces flexibility permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/professionalism/paradigm/oop.png&quot; alt=&quot;OO programming&quot;&gt; &lt;/p&gt;
&lt;p&gt;Object-Oriented programming. OOP is concerned with how we structure the relationships between our classes that &lt;em&gt;contain&lt;/em&gt; the methods that execute our (imperative) algorithms and procedures. &lt;/p&gt;
&lt;p&gt;At this level, the principles that dictate how we do this is a lot less clear. &lt;/p&gt;
&lt;p&gt;Because of the &lt;em&gt;lack of specific ubiquitous rules to follow&lt;/em&gt; in addition to the total number of possible ways to structure a system, it can be pretty challenging to learn. This is the basis for studying software design and architecture.&lt;/p&gt;
&lt;h3 id=&quot;Software-architects-spend-a-lot-of-time-at-this-layer&quot; style=&quot;position:relative;&quot;&gt;Software architects spend a lot of time at this layer&lt;a href=&quot;#Software-architects-spend-a-lot-of-time-at-this-layer&quot; aria-label=&quot;Software architects spend a lot of time at this layer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We&apos;ve discussed previously that when you&apos;re programming, you&apos;re either writing &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;detail or policy&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;When your current goal is to define relationships between high-level constructs and policies between them (through interfaces and abstractions), OOP&apos;s polymorhism allows developers to &lt;a href=&quot;/wiki/dependency-inversion/&quot;&gt;flip the dependency graph&lt;/a&gt; to defer design decisions, enabling the &lt;strong&gt;details&lt;/strong&gt; to be filled in later.&lt;/p&gt;
&lt;p&gt;OOP solves a lot of problems, but &lt;em&gt;its a steep learning curve&lt;/em&gt; to learn how to use it to solve the problems that it&apos;s meant to address.&lt;/p&gt;
&lt;h3 id=&quot;Domain-knowledge-required&quot; style=&quot;position:relative;&quot;&gt;Domain-knowledge required&lt;a href=&quot;#Domain-knowledge-required&quot; aria-label=&quot;Domain knowledge required permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Not only do we need to learn the basics of object-modeling, but we are also tasked with &lt;strong&gt;understanding the domain&lt;/strong&gt;, which is something that most developers just don&apos;t want to do.&lt;/p&gt;
&lt;p&gt;This is why many developers new to OOP end up with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;classes that sound computery &lt;code class=&quot;language-text&quot;&gt;[Something]Factory&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;[Something]Manager&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;[Something]Processor&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Utilizing a Rich Domain Model, we can solve business challenges in a more declarative way, requiring less new code to solve future problems.&lt;/p&gt;
&lt;p&gt;Failure to recognize when it&apos;s time to switch could be deadly to a project or organization&apos;s productivity.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/wiki/anemic/chart.svg&quot; alt=&quot;Anemic Domain Model&quot;&gt; &lt;/p&gt;
&lt;p&gt;Polymorhism and a &lt;a href=&quot;/articles/typescript-domain-driven-design/ddd-vs-crud-design/&quot;&gt;declarative&lt;/a&gt;, &lt;a href=&quot;https://www.codingblocks.net/podcast/supple-design/&quot;&gt;supple design&lt;/a&gt; dramatically improves &lt;code class=&quot;language-text&quot;&gt;flexibility&lt;/code&gt; &lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;That being said, when we’re designing systems, there is no dominant programming paradigm. &lt;/p&gt;
&lt;p&gt;You could restrict yourself to only using one paradigm (like a lot of functional programmers may), although you’ll find that it’s challenging. Not impossible, but challenging. &lt;sup id=&quot;fnref-3&quot;&gt;&lt;a href=&quot;#fn-3&quot; class=&quot;footnote-ref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;And that’s because “a well-designed system is all three at the same time”. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/professionalism/paradigm/all-paradigms.png&quot; alt=&quot;OO programming&quot;&gt; &lt;/p&gt;
&lt;p&gt;There are certain cases where the best approach for a task will be an imperative one, and there are times where a functional approach is preferred.&lt;/p&gt;
&lt;h2 id=&quot;Takeaways&quot; style=&quot;position:relative;&quot;&gt;Takeaways&lt;a href=&quot;#Takeaways&quot; aria-label=&quot;Takeaways permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&apos;s what we&apos;ve covered in this article:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Quality software is &lt;code class=&quot;language-text&quot;&gt;reliable&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;flexible&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;maintainable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Imperative programming is where we define what &lt;em&gt;actually&lt;/em&gt; happens behind the scenes. It determines if the software actually lives up to it&apos;s responsibilities. This paradigm governs &lt;code class=&quot;language-text&quot;&gt;reliability&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Functional programming concepts urge us to limit side-effects because it improves &lt;code class=&quot;language-text&quot;&gt;maintainability&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Object-oriented programming is how we define the relationships between our modules, manage dependencies and encapsulate business logic. When we excell here, our software is supple, declarative, and &lt;code class=&quot;language-text&quot;&gt;flexible&lt;/code&gt; to the guaranteed changes that are sure to occur in a project&apos;s lifetime.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; - In Fowler&apos;s Patterns of Enterprise Application Architecture, using a Transaction Script &lt;a href=&quot;https://www.amazon.ca/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420&quot;&gt;(Fowler - PoEAA)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; - &lt;strong&gt;Supple Design&lt;/strong&gt; is a concept from Domain-Driven Design where &quot;Complex logic is encapsulated, side effects are minimized and suppled up, and dependencies are minimized&quot;. &lt;a href=&quot;https://www.codingblocks.net/podcast/supple-design/&quot;&gt;https://www.codingblocks.net/podcast/supple-design/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;sup id=&quot;fnref-3&quot;&gt;&lt;a href=&quot;#fn-3&quot; class=&quot;footnote-ref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; - See Scott  Wlaschin&apos;s book on &lt;a href=&quot;https://www.amazon.com/Domain-Modeling-Made-Functional-Domain-Driven/dp/1680502549&quot;&gt;Domain Modeling with F#&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Intention Revealing Interfaces [w/ Examples] - Domain-Driven Design w/ TypeScript]]></title><description><![CDATA[Have you ever heard someone say that your code should be so well-understood that it should be read like a book? Those are the same…]]></description><link>https://khalilstemmler.com/articles/typescript-domain-driven-design/intention-revealing-interfaces/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/typescript-domain-driven-design/intention-revealing-interfaces/</guid><pubDate>Tue, 09 Jul 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;course-cta&quot;&gt;
We cover this topic in &lt;a href=&quot;https://www.essentialist.dev/master-the-essentials-of-software-design-with-typescript&quot;&gt;The Software Essentialist&lt;/a&gt; online course. Check it out if you liked this post.
&lt;/p&gt;
&lt;p&gt;Have you ever heard someone say that your code should be &lt;em&gt;so&lt;/em&gt; well-understood that it should be read like a book?&lt;/p&gt;
&lt;p&gt;Those are the same developers who are usually &lt;strong&gt;against writing comments&lt;/strong&gt;. Their argument is that comments are non-ideal because as soon as code gets changed, comments go out of date really quickly.&lt;/p&gt;
&lt;p&gt;I tend to agree with that.&lt;/p&gt;
&lt;p&gt;I think there&apos;s a more important reason why your code should be well-understood.&lt;/p&gt;
&lt;p&gt;When new developers join your company and start to peer through your codebase, new developers might struggle with &lt;strong&gt;how&lt;/strong&gt; to use your code.&lt;/p&gt;
&lt;p&gt;More critically, even if it&apos;s undertstood &lt;em&gt;how&lt;/em&gt; to use something, new developers might struggle with &lt;em&gt;when&lt;/em&gt; it&apos;s the right choice to use that particular class or method.&lt;/p&gt;
&lt;p&gt;In previous articles, we talked about the fact that &lt;a href=&quot;/articles/solid-principles/single-responsibility/&quot;&gt;understanding the domain is &lt;em&gt;key&lt;/em&gt; to implementing the single responsibility principle&lt;/a&gt; properly and writing decoupled code.&lt;/p&gt;
&lt;p&gt;In this article, we&apos;re going to explore what it means to write &lt;strong&gt;Intention Revealing Interfaces&lt;/strong&gt; and how it enables you to write code that improves comprehension as to &lt;strong&gt;how&lt;/strong&gt; and &lt;strong&gt;when&lt;/strong&gt; a particular class or method should be used.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In Eric Evans&apos; seminal book about &lt;a href=&quot;https://www.amazon.ca/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=asc_df_0321125215/?tag=googleshopc0c-20&amp;#x26;linkCode=df0&amp;#x26;hvadid=292950359971&amp;#x26;hvpos=1o2&amp;#x26;hvnetw=g&amp;#x26;hvrand=2413492730734697031&amp;#x26;hvpone=&amp;#x26;hvptwo=&amp;#x26;hvqmt=&amp;#x26;hvdev=c&amp;#x26;hvdvcmdl=&amp;#x26;hvlocint=&amp;#x26;hvlocphy=9000812&amp;#x26;hvtargid=pla-449269547899&amp;#x26;psc=1&quot;&gt;Domain-Driven Design&lt;/a&gt;, he describes the need for something called an &lt;strong&gt;Intention Revealing Interface&lt;/strong&gt; with respect to choosing the names for our classes, methods, etc.&lt;/p&gt;
&lt;p&gt;Very simply put, &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Name classes and operations to describe their effect and purpose, without reference to the means by which they do what they promise. - Los Techies &lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In my own words, an Intention-Revealing interface is:&lt;/p&gt;
&lt;p&gt;Writing code... that reveals... the intention... to others! &lt;/p&gt;
&lt;p&gt;And doing that without regard for expressing &lt;em&gt;how&lt;/em&gt; it does it (ie: &lt;strong&gt;encapsulation&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;Also, when we say &lt;strong&gt;interfaces&lt;/strong&gt; here, we’re not necessarily referring to the &lt;code class=&quot;language-text&quot;&gt;interface&lt;/code&gt; that you and I best know: the OOP construct. In this case, we’re just referring to an interface as &lt;em&gt;whatever the client&lt;/em&gt; (be that a consumer of an SDK, and API, or a junior developer joining our company) &lt;em&gt;using our code will see&lt;/em&gt;. We&apos;re referring to it more as &quot;how the client uses our code&quot;.&lt;/p&gt;
&lt;h2 id=&quot;The-client-doesnt-need-to-know&quot; style=&quot;position:relative;&quot;&gt;The client doesn&apos;t need to know&lt;a href=&quot;#The-client-doesnt-need-to-know&quot; aria-label=&quot;The client doesnt need to know permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I was having a discussion with a colleague the other day about if it was OK to run additional logic in a &lt;code class=&quot;language-text&quot;&gt;getter&lt;/code&gt; without letting the client explictly know if we&apos;re doing that.&lt;/p&gt;
&lt;p&gt;Of course it is.&lt;/p&gt;
&lt;p&gt;Let&apos;s say we wanted to return the most popular &lt;code class=&quot;language-text&quot;&gt;tracks&lt;/code&gt; that were topping the charts.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Chart&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;popularTracks&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Track &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tracks
      &lt;span class=&quot;token comment&quot;&gt;// Filter out tracks with no listens&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;track&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; track&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;listens&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Sort them descending&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;listens&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;listens&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is basic OOP encapsulation. Consider the additional mental overhead if everytime we wanted to use a method or access a property, we had to look up the documentation for it to see if it was really the right one for us to use.&lt;/p&gt;
&lt;h3 id=&quot;Creating-Domain-Events&quot; style=&quot;position:relative;&quot;&gt;Creating Domain Events&lt;a href=&quot;#Creating-Domain-Events&quot; aria-label=&quot;Creating Domain Events permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the previous article about &lt;a href=&quot;/blogs/domain-driven-design/where-do-domain-events-get-dispatched/&quot;&gt;where Domain Events get created&lt;/a&gt;, we demonstrated that sometimes we want to dispatch Domain Events within method calls or intercepted &lt;code class=&quot;language-text&quot;&gt;getters&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;setters&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Consider if we wanted to do some &lt;strong&gt;change tracking&lt;/strong&gt; on our &lt;code class=&quot;language-text&quot;&gt;Artist&lt;/code&gt; domain entity from &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;White Label&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;How would we go about creating a &lt;code class=&quot;language-text&quot;&gt;ArtistEdited&lt;/code&gt; domain event?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Artist&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; dirty&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// intercept our setter&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;markDirty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;markDirty&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dirty&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dirty &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDomainEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ArtistEditedEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That ability to intercept changes to our domain model with &lt;a href=&quot;/blogs/typescript/getters-and-setters/&quot;&gt;getters and setters&lt;/a&gt; and create Domain Events that signify relevant occurrences in our domain, while saying &lt;em&gt;no more than necessary&lt;/em&gt; to the client of the API (through encapsulation) moves us closer to a &lt;a href=&quot;/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;rich declarative domain model&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;How-to-know-when-our-ability-to-express-intention-is-lost&quot; style=&quot;position:relative;&quot;&gt;How to know when our ability to express intention is lost&lt;a href=&quot;#How-to-know-when-our-ability-to-express-intention-is-lost&quot; aria-label=&quot;How to know when our ability to express intention is lost permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here’s what Evans says on how to know when we&apos;ve run amuck.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If a developer must consider the implementation of a component in order to use it, the value of encapsulation is lost.  - Evans (DDD)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If developers need to &lt;em&gt;know&lt;/em&gt; &lt;strong&gt;how&lt;/strong&gt; something&apos;s works before they use it, then we’ve lost encapsulation.&lt;/p&gt;
&lt;p&gt;Alright, so how &lt;em&gt;do&lt;/em&gt; we write code that tells other developers &lt;em&gt;what&lt;/em&gt; is done without having to show them exactly &lt;em&gt;how&lt;/em&gt; it’s done?&lt;/p&gt;
&lt;p&gt;Two ways.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Encapsulate&lt;/strong&gt; things that aren’t necessary for other developers to know about, and &lt;/li&gt;
&lt;li&gt;We &lt;strong&gt;name things really well&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We’ve talked about all the benefits of &lt;strong&gt;encapsulation&lt;/strong&gt; in object-oriented programming, but in Domain-Driven Design, there’s an even more essential reason why it’s important. &lt;/p&gt;
&lt;p&gt;One of the primary goals of Domain-Driven Design is to &quot;embed the domain terminology in the code&quot; &lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. &lt;/p&gt;
&lt;p&gt;Ideally, we would like to end up with an entire system that’s &lt;strong&gt;more declarative&lt;/strong&gt; than imperative, can be understood by non-coders and domain experts, and educates newly onboarded developers about how the business actually works because the software is a &lt;strong&gt;in-code representation&lt;/strong&gt; and solution of the actual problem domain.&lt;/p&gt;
&lt;p&gt;That means we should check our variable names, methods, classes and Domain Events to ensure that we’ve effectively &quot;capture[d] the domain model, in domain terms, through interactions with domain experts” &lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. &lt;/p&gt;
&lt;h2 id=&quot;Lets-make-it-perfectly-understood-exactly-what-this-class-is-for&quot; style=&quot;position:relative;&quot;&gt;Let’s make it perfectly understood exactly what this class is for&lt;a href=&quot;#Lets-make-it-perfectly-understood-exactly-what-this-class-is-for&quot; aria-label=&quot;Lets make it perfectly understood exactly what this class is for permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;If someone other than the original developer must infer the purpose of an object or operation based on its implementation, that new developer may infer a purpose that the operation or class fulfills only by chance. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We should aim to be writing code that is irrefutable about what it &lt;em&gt;is&lt;/em&gt; and what it &lt;em&gt;does&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In fact, this is the primary theme of my short ebook &lt;a href=&quot;/resources/names-construct-structure&quot;&gt;“Name, Construct &amp;#x26; Structure”&lt;/a&gt; and my approach to organizing features with &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use cases&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For example, a good practice for naming classes is to ensure that the &lt;strong&gt;actual name&lt;/strong&gt; dictates what type of construct it is: &lt;/p&gt;
&lt;p&gt;Therefore: &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;UserRepository&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;UserMapper&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Check out the &lt;a href=&quot;/resources/names-construct-structure&quot;&gt;free book&lt;/a&gt; if you&apos;re interested in learning more about how to name things.&lt;/p&gt;
&lt;h2 id=&quot;Lets-make-it-perfectly-understood-what-this-method-needs&quot; style=&quot;position:relative;&quot;&gt;Let’s make it perfectly understood what this method needs&lt;a href=&quot;#Lets-make-it-perfectly-understood-what-this-method-needs&quot; aria-label=&quot;Lets make it perfectly understood what this method needs permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Have you ever seen code like this? Here’s an example I got from &lt;a href=&quot;https://lostechies.com/jimmybogard/2007/11/29/intention-concealing-interfaces-blob-parameters/&quot;&gt;Los Techies&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MakeOffer&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinyl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; trader1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; trader2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Apparently this type of thing is pretty common in the Java and C# world as &lt;strong&gt;blob&lt;/strong&gt; parameters.&lt;/p&gt;
&lt;p&gt;In this &lt;code class=&quot;language-text&quot;&gt;MakeOffer&lt;/code&gt; class, it’s probably well understood that the &lt;a href=&quot;/articles/solid-principles/single-responsibility/&quot;&gt;single responsibility&lt;/a&gt; is to make an offer, but the parameter &lt;code class=&quot;language-text&quot;&gt;items&lt;/code&gt; in the &lt;code class=&quot;language-text&quot;&gt;execute&lt;/code&gt; method doesn’t &lt;strong&gt;reveal anything&lt;/strong&gt; about what we were intended to pass in.&lt;/p&gt;
&lt;h2 id=&quot;Lets-make-it-perfectly-understood-what-this-class-is-not-for&quot; style=&quot;position:relative;&quot;&gt;Let’s make it perfectly understood what this class is &lt;em&gt;not&lt;/em&gt; for&lt;a href=&quot;#Lets-make-it-perfectly-understood-what-this-class-is-not-for&quot; aria-label=&quot;Lets make it perfectly understood what this class is not for permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;If [code used in one way] was not the intent, the code may work for the moment, but the conceptual basis of the design will have been corrupted, and the two developers will be working at cross-purposes. - Evans (DDD)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is exactly what we strive so very hard to avoid. &lt;/p&gt;
&lt;p&gt;Consider we were  building the &lt;code class=&quot;language-text&quot;&gt;Billing&lt;/code&gt; subdomain in our &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;Vinyl Trading App&lt;/a&gt; and we had a &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;Use Case&lt;/a&gt; called &lt;code class=&quot;language-text&quot;&gt;BillCustomer&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BillCustomerUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;customerItem&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	  &lt;span class=&quot;token comment&quot;&gt;// algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At this point, you might ask me something like: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“uhh.. Khalil, why isn’t there something in there to dictate the amount of money you’re going to bill the customer? Don’t you need to pass that in as well?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sure. That’s one way you &lt;em&gt;could&lt;/em&gt; look at it. &lt;/p&gt;
&lt;p&gt;You could look at it as if the &lt;code class=&quot;language-text&quot;&gt;BillCustomerUseCase&lt;/code&gt; is a &lt;strong&gt;general&lt;/strong&gt; use case that takes in an &lt;strong&gt;amount&lt;/strong&gt; and a &lt;code class=&quot;language-text&quot;&gt;customer&lt;/code&gt; in order to bill them.&lt;/p&gt;
&lt;p&gt;But yes, correct. That’s not very explicit from the design.&lt;/p&gt;
&lt;p&gt;Perhaps, you might see it a different way.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;customerItem&lt;/code&gt;. does that mean I pass in a customer? Or is &lt;code class=&quot;language-text&quot;&gt;customerItem&lt;/code&gt; the item that we’re billing the customer with? Wait. If I pass in an item, like &lt;code class=&quot;language-text&quot;&gt;vinyl&lt;/code&gt;, how is it going to know which &lt;code class=&quot;language-text&quot;&gt;customer&lt;/code&gt; to bill? Is there an object for this? Is there something that contains both the &lt;code class=&quot;language-text&quot;&gt;itemId&lt;/code&gt; and the &lt;code class=&quot;language-text&quot;&gt;customerId&lt;/code&gt;? It would have been really helpful if I knew what the type needed here was... &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It&apos;s much harder to reason about code without types, and that&apos;s why &lt;a href=&quot;/articles/when-to-use-typescript-guide/&quot;&gt;typescript is such a great choice for domain modeling&lt;/a&gt;, but there&apos;s another problem with this code. &lt;/p&gt;
&lt;p&gt;Let’s say that someone got this working to do &lt;strong&gt;transactional charging&lt;/strong&gt;; meaning you get charged for every transaction of a single item.&lt;/p&gt;
&lt;p&gt;Nice.&lt;/p&gt;
&lt;p&gt;Then, another developer comes along, takes one look at the code, and says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is &lt;em&gt;definitely&lt;/em&gt; for billing subscriptions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Maybe that other developer considers the absence of an &lt;code class=&quot;language-text&quot;&gt;amount&lt;/code&gt; parameter to signify that this use case meant for charging customers on &lt;strong&gt;recurring charges&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;At that point, both developers are using this function for two separate reasons.&lt;/p&gt;
&lt;p&gt;This is what Evans was warning us about when he said that the “conceptual basis of the design will have been corrupted” if two developers are working “at cross-purpose[s]”.&lt;/p&gt;
&lt;p&gt;We’ve already seen what happens when developers add code to something that changes for two very different reasons. That coupling becomes a big problem when those two different features evolve in different ways. An adjustment to one feature has the repeated risk to break the other. &lt;/p&gt;
&lt;p&gt;This violation of the &lt;a href=&quot;/articles/solid-principles/solid-typescript/#SRP&quot;&gt;single responsibility principle&lt;/a&gt; could have been avoided if we had used &lt;strong&gt;intention-revealing interfaces&lt;/strong&gt; (ie: better names) and types for the parameters.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Vinyl can be purchased&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PurchasedVinyl&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;amount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; amount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AnnualSubscription&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Subscription&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;amount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; amount&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BillCustomerUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Explicit parameters&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;customer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Customer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; product&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Product&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	  &lt;span class=&quot;token comment&quot;&gt;// Execute algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice the improvement here? We&apos;re explicitly specifying what&apos;s required in the parameters here: a &lt;code class=&quot;language-text&quot;&gt;customer&lt;/code&gt; and a &lt;code class=&quot;language-text&quot;&gt;product&lt;/code&gt;. And it just so happens that with this design, we &lt;em&gt;do&lt;/em&gt; charge transactionally, and a &lt;code class=&quot;language-text&quot;&gt;Subscription&lt;/code&gt; is a type of &lt;code class=&quot;language-text&quot;&gt;product&lt;/code&gt; that we could charge for.&lt;/p&gt;
&lt;h3 id=&quot;Constantly-ask-yourself-if-the-terminology-sounds-too-techy&quot; style=&quot;position:relative;&quot;&gt;Constantly ask yourself if the terminology sounds too &quot;techy&quot;&lt;a href=&quot;#Constantly-ask-yourself-if-the-terminology-sounds-too-techy&quot; aria-label=&quot;Constantly ask yourself if the terminology sounds too techy permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Try really hard not to use words that sound &quot;techy&quot; like &lt;code class=&quot;language-text&quot;&gt;Processor&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Creator&lt;/code&gt; or and &lt;code class=&quot;language-text&quot;&gt;Manager&lt;/code&gt; for the names of your &lt;a href=&quot;&quot;&gt;domain layer&lt;/a&gt; constructs. &lt;/p&gt;
&lt;p&gt;If you notice that seems to be the case, there&apos;s a chance that you might have run amuck.&lt;/p&gt;
&lt;p&gt;The language we use in the code should be similar to the language that the domain-experts use in the real world. &lt;/p&gt;
&lt;p&gt;&lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; Another great read on intention revealing interfaces. &lt;a href=&quot;https://lostechies.com/jimmybogard/2007/11/29/intention-concealing-interfaces-blob-parameters/&quot;&gt;https://lostechies.com/jimmybogard/2007/11/29/intention-concealing-interfaces-blob-parameters/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; Here&apos;s a great article by Steven A. Lowe on the 3 basic principles of Domain-Driven Design. He&apos;s currently working on his &quot;Head First Domain-Driven Design&quot; book. &lt;a href=&quot;https://techbeacon.com/app-dev-testing/get-your-feet-wet-domain-driven-design-3-guiding-principles&quot;&gt;https://techbeacon.com/app-dev-testing/get-your-feet-wet-domain-driven-design-3-guiding-principles&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[All about TypeScript Static Members | TypeScript OOP]]></title><description><![CDATA[In Object-Oriented Programming, we write a lot of classes. Classes contain properties (methods and attributes) which hold variables and…]]></description><link>https://khalilstemmler.com/blogs/typescript/static-members/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/typescript/static-members/</guid><pubDate>Sun, 07 Jul 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;In Object-Oriented Programming, &lt;u&gt;we write a lot of &lt;em&gt;classes&lt;/em&gt;&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;Classes contain &lt;em&gt;properties&lt;/em&gt; (&lt;strong&gt;methods&lt;/strong&gt; and &lt;strong&gt;attributes&lt;/strong&gt;) which hold variables and operations.&lt;/p&gt;
&lt;p&gt;Every time we define the properties of a class, they are said to belong to either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an &lt;em&gt;instance&lt;/em&gt; of the class (an object created via constructor) OR&lt;/li&gt;
&lt;li&gt;the class &lt;em&gt;itself&lt;/em&gt; (we call this a class member)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;What do we mean by that?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;How can properties belong to only the &lt;em&gt;instance&lt;/em&gt; vs. only the &lt;em&gt;class&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;When we choose to use or omit the &lt;code class=&quot;language-text&quot;&gt;static&lt;/code&gt; keyword, it changes who the properties belong to.&lt;/p&gt;
&lt;p&gt;Let&apos;s look at regular usage without the &lt;code class=&quot;language-text&quot;&gt;static&lt;/code&gt; keyword.&lt;/p&gt;
&lt;h2 id=&quot;Regular-usage-properties-belong-to-the-instance&quot; style=&quot;position:relative;&quot;&gt;Regular usage (properties belong to the instance)&lt;a href=&quot;#Regular-usage-properties-belong-to-the-instance&quot; aria-label=&quot;Regular usage properties belong to the instance permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Normally, when we define properties on a class, the only time they can be &lt;em&gt;accessed&lt;/em&gt; is &lt;strong&gt;after&lt;/strong&gt; we&apos;ve created an instance of that class or if we use &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; to refer to the properties that will eventually reside on an instance of the object.&lt;/p&gt;
&lt;p&gt;Take this early example from &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;White Label&lt;/a&gt;. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Genre &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;rock&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pop&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;electronic&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;rap&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; genres&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;printSummary&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; is an album by &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinyl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Goo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Sonic Youth&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;rock&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// &apos;Goo&apos;&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;// &apos;Sonic Youth&apos;&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;// [&apos;rock&apos;]&lt;/span&gt;
vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;printSummary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;	      &lt;span class=&quot;token comment&quot;&gt;// &apos;Goo is an album by Sonic Youth&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Each of the methods (&lt;code class=&quot;language-text&quot;&gt;printSummary(): void&lt;/code&gt;) and attributes (&lt;code class=&quot;language-text&quot;&gt;title&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;artist&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;genres&lt;/code&gt;) on the &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; class are said to belong to an &lt;em&gt;instance&lt;/em&gt; of the class.&lt;/p&gt;
&lt;p&gt;In the example, we were only able to access the properties &lt;code class=&quot;language-text&quot;&gt;title&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;artist&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;genres&lt;/code&gt; directly from the object &lt;em&gt;after&lt;/em&gt; it was created.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// This is valid!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Also note that when we use &lt;code class=&quot;language-text&quot;&gt;printSummary(): void&lt;/code&gt;, we can access &lt;code class=&quot;language-text&quot;&gt;title&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;artist&lt;/code&gt; using the &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; keyword:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;printSummary&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; is an album by &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That works because at this point, the resulting object / instance of &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; owns those properties.&lt;/p&gt;
&lt;p&gt;If we check out &lt;a href=&quot;http://www.typescriptlang.org/play/&quot;&gt;TypeScript Playground&lt;/a&gt;, we can look at the compiled JavaScript for this code sample:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; artist&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; genres&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; genres&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;printSummary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; is an album by &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinyl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Goo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Sonic Youth&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;rock&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &apos;Goo&apos;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &apos;Sonic Youth&apos;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [&apos;rock&apos;]&lt;/span&gt;
vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;printSummary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &apos;Goo is an album by Sonic Youth&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The resulting JavaScript looks &lt;em&gt;nearly identical&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Let&apos;s talk a bit about what happens when the properties are owned by the &lt;em&gt;class&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Static-properties-properties-belong-to-the-class&quot; style=&quot;position:relative;&quot;&gt;Static properties (properties belong to the class)&lt;a href=&quot;#Static-properties-properties-belong-to-the-class&quot; aria-label=&quot;Static properties properties belong to the class permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When we use the &lt;code class=&quot;language-text&quot;&gt;static&lt;/code&gt; keyword on properties we define on a class, they belong to &lt;em&gt;the class itself&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;That means that we &lt;u&gt;cannot&lt;/u&gt; access those properties from an instance of the class.&lt;/p&gt;
&lt;p&gt;We can only access the properties directly by referencing the class itself.&lt;/p&gt;
&lt;p&gt;To demonstrate, let&apos;s add a counter &lt;code class=&quot;language-text&quot;&gt;NUM_VINYL_CREATED&lt;/code&gt; that increments the number of times that a &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; was created.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Genre &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;rock&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pop&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;electronic&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;rap&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NUM_VINYL_CREATED&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; genres&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	Vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NUM_VINYL_CREATED&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// increment number of vinyl created&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NUM_VINYL_CREATED&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;printSummary&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; is an album by &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; goo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Goo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Sonic Youth&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;rock&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// prints out 1&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; daydream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Daydream Nation&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Sonic Youth&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;rock&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// prints out 2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Because the properties can only be accessed through the class by referring to the &lt;em&gt;class name&lt;/em&gt; itself, we &lt;strong&gt;can&apos;t access static properties&lt;/strong&gt; through an &lt;em&gt;instance&lt;/em&gt; like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; goo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Goo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Sonic Youth&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;rock&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
goo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MAX_GENRES_PER_VINYL&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// Error&lt;/span&gt;
goo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NUM_VINYL_CREATED&lt;/span&gt;       &lt;span class=&quot;token comment&quot;&gt;// Error&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You might have heard of a term called &lt;strong&gt;Class Members&lt;/strong&gt;. An attribute or a method is a &lt;em&gt;class member&lt;/em&gt; because they can ONLY be accessed through the class itself; therefore, they&apos;re members of the class.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;/**
   * Example &quot;Class Member&quot; (sometimes known as 
   * &quot;Static Class Member&quot;) variable.
   * 
   * Can only be accessed through mentioning the class name
   * itself:
   * 
   * Example: const vinylCreatedToDate = Vinyl.NUM_VINYL_CREATED;
   */&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NUM_VINYL_CREATED&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

  &lt;span class=&quot;token comment&quot;&gt;/**
   * Example &quot;Instance Member&quot; variable.
   * 
   * Can only be accessed through an instance/object created from 
   * this class.
   * 
   * Example: 
   *  
   *  const blueAlbum = new Vinyl(&quot;Blue Album&quot;);
   *  console.log(blueAlbum.title); // &quot;Blue Album&quot;
   */&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;The different types of &lt;i&gt;member variables&lt;/i&gt; that can appear on a class.&lt;/p&gt;
&lt;p&gt;That&apos;s great and all, but &lt;em&gt;when would you want to use static properties?&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;How-to-know-when-to-use-static-properties&quot; style=&quot;position:relative;&quot;&gt;How to know when to use static properties&lt;a href=&quot;#How-to-know-when-to-use-static-properties&quot; aria-label=&quot;How to know when to use static properties permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before you add that attribute or method, ask yourself:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Will this property ever need to be used by another class, without first needing to create an object of it?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In other words, should I need to call it on an &lt;strong&gt;object&lt;/strong&gt; created by this class or not? If yes, then continue normally. &lt;/p&gt;
&lt;p&gt;If no, then you might want to make a &lt;code class=&quot;language-text&quot;&gt;static&lt;/code&gt; member.&lt;/p&gt;
&lt;h3 id=&quot;Scenarios-where-it-could-make-sense-to-use-a-static-property&quot; style=&quot;position:relative;&quot;&gt;Scenarios where it could make sense to use a static property&lt;a href=&quot;#Scenarios-where-it-could-make-sense-to-use-a-static-property&quot; aria-label=&quot;Scenarios where it could make sense to use a static property permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;to check a business rule or constraint from another class&lt;/li&gt;
&lt;li&gt;to implement a &lt;code class=&quot;language-text&quot;&gt;factory method&lt;/code&gt; to &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;encapsulate the complexity&lt;/a&gt; required in order to create an instance of the class&lt;/li&gt;
&lt;li&gt;to use an &lt;code class=&quot;language-text&quot;&gt;abstract factory&lt;/code&gt; in order &lt;a href=&quot;/wiki/abstract-factory/&quot;&gt;to create a specific type of instance of the class&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;when the property shouldn&apos;t ever change&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Scenarios-where-it-seems-like-it-might-make-sense-but-actually-leads-to-an-anemic-domain-model&quot; style=&quot;position:relative;&quot;&gt;Scenarios where it &lt;em&gt;seems like&lt;/em&gt; it might make sense but actually leads to an &lt;a href=&quot;/wiki/anemic-domain-model/&quot;&gt;anemic domain model&lt;/a&gt;:&lt;a href=&quot;#Scenarios-where-it-seems-like-it-might-make-sense-but-actually-leads-to-an-anemic-domain-model&quot; aria-label=&quot;Scenarios where it seems like it might make sense but actually leads to an anemic domain model permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;to perform validation logic on atttributes for that class (use &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;Value Objects&lt;/a&gt; instead)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To demonstrate a worthwhile scenario, let&apos;s add a &lt;code class=&quot;language-text&quot;&gt;static&lt;/code&gt; &lt;code class=&quot;language-text&quot;&gt;MAX_GENRES_PER_VINYL&lt;/code&gt; attribute to &quot;document a constraint&quot; that a &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; may only have at max 2 different types of &lt;code class=&quot;language-text&quot;&gt;Genres&lt;/code&gt;. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Genre &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;rock&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pop&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;electronic&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;rap&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MAX_GENRES_PER_VINYL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; genres&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;printSummary&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; is an album by &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then let&apos;s add an &lt;code class=&quot;language-text&quot;&gt;addGenre(genre: Genre): void&lt;/code&gt; method to enforce this business rule.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Genre &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;rock&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pop&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;electronic&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;rap&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MAX_GENRES_PER_VINYL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; genres&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addGenre&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;genre&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Notice that in order to reference the value, we have go through the class&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// itself (Vinyl), not through an instance of the class (this).&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maxLengthExceeded &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MAX_GENRES_PER_VINYL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; alreadyAdded &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; g &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; genre&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;maxLengthExceeded &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;alreadyAdded&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;genre&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;printSummary&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; is an album by &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Where Do Domain Events Get Created? | Domain Driven Design w/ TypeScript]]></title><description><![CDATA[Last time, we talked about how to create a facade over our ORM using the Repository pattern. Today, we're talking a little bit about where…]]></description><link>https://khalilstemmler.com/blogs/domain-driven-design/where-do-domain-events-get-dispatched/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/domain-driven-design/where-do-domain-events-get-dispatched/</guid><pubDate>Thu, 04 Jul 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Last time, we talked about how to create a &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;facade over our ORM using the Repository pattern&lt;/a&gt;. Today, we&apos;re talking a little bit about where we create Domain Events.&lt;/p&gt;
&lt;p&gt;Domain Events are a &lt;em&gt;huge&lt;/em&gt; part of Domain-Driven Design. &lt;/p&gt;
&lt;p&gt;When implemented correctly, they allow us to &lt;strong&gt;chain&lt;/strong&gt; domain logic, maintain &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;single responsibility&lt;/a&gt;, and cross architectural boundaries (subdomains) using the Observer pattern (which is a well-known way to separate concerns and decouple async logic).&lt;/p&gt;
&lt;p&gt;The question is: &quot;where do Domain Events get created&quot;? &lt;/p&gt;
&lt;p&gt;Domain Events are a part of the &lt;strong&gt;domain layer&lt;/strong&gt;, so they belong with all the other domain layer constructs like &lt;a href=&quot;/articles/typescript-domain-driven-design/entities/&quot;&gt;entities&lt;/a&gt;, &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;value objects&lt;/a&gt; and &lt;strong&gt;domain services&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;OK cool, but where &lt;em&gt;exactly&lt;/em&gt; do they get created?&lt;/p&gt;
&lt;p&gt;Right on the &lt;strong&gt;aggregate root&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Allow me to explain.&lt;/p&gt;
&lt;p&gt;To me, the most beautiful thing about &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design&lt;/a&gt; is that it urges you towards creating your own &lt;strong&gt;domain-specific language (DSL)&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;You expose only the methods and attributes that &lt;u&gt;make sense&lt;/u&gt; to the domain. And those methods and attributes only belong on &lt;strong&gt;entities&lt;/strong&gt; and &lt;strong&gt;value objects&lt;/strong&gt; that it &lt;u&gt;makes sense&lt;/u&gt; to belong on.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// factory method to create users, yep&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  

  &lt;span class=&quot;token comment&quot;&gt;// yup, also a valid domain operation&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;deactivate&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;       
  
  &lt;span class=&quot;token comment&quot;&gt;// ❌ No. A client shouldn&apos;t need to use this operation.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Use a Value Object to encapsulate validation logic instead: &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// https://khalilstemmler.com/articles/typescript-value-object/  &lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validateFirstName&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;firstName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;            
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Determining what &lt;strong&gt;makes sense&lt;/strong&gt; is &lt;em&gt;hard&lt;/em&gt;. It usually takes a lot of conversation with domain experts and multiple iterations of the model.&lt;/p&gt;
&lt;p&gt;This increased importance on &lt;a href=&quot;/wiki/yagni/&quot;&gt;YAGNI&lt;/a&gt;, and only exposing operations that are valid to the model are also a big reason why &lt;a href=&quot;/blogs/typescript/getters-and-setters/&quot;&gt;getters and setters&lt;/a&gt; get a lot of usage for us in Domain-Driven Design. &lt;/p&gt;
&lt;p&gt;Using getters and setters, not only do we get to specify exactly &lt;strong&gt;what&lt;/strong&gt; is allowed to be accessed/changed, but we also get to specify &lt;em&gt;when&lt;/em&gt; it&apos;s allowed to be accessed/changed, and &lt;em&gt;what happens&lt;/em&gt; when it&apos;s accessed/changed. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When &lt;em&gt;essential&lt;/em&gt; properties are accessed or changed, it might make sense to create a Domain Event.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For example, if we were working on &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;White Label&lt;/a&gt;&apos;s feature that enables &lt;code class=&quot;language-text&quot;&gt;Traders&lt;/code&gt; to &lt;em&gt;accept&lt;/em&gt; or &lt;em&gt;decline&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;Offers&lt;/code&gt;, we&apos;d have to walk through the process of &lt;a href=&quot;/articles/software-design-architecture/organizing-app-logic/&quot;&gt;determining where Domain Logic should belong&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Following that process, we&apos;d discover that &lt;code class=&quot;language-text&quot;&gt;acceptOffer()&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;declineOffer()&lt;/code&gt; perform &lt;u&gt;mutations&lt;/u&gt; to the &lt;code class=&quot;language-text&quot;&gt;Offer&lt;/code&gt; aggregate root itself. &lt;/p&gt;
&lt;p&gt;Those operations can be done without the involvement of any other domain entities, so it makes sense to locate them directly on the &lt;code class=&quot;language-text&quot;&gt;Offer&lt;/code&gt; aggregate root.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; OfferState &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;initial&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;accepted&apos;&lt;/span&gt;  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;declined&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;OfferProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; OfferState&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Offer&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;OfferProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;offerId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; OfferId &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; OfferId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;offerState&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; OfferState &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;acceptOffer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;offerState&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;initial&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Notice how there is not a public setter for the&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// &apos;state&apos; attribute. That&apos;s because it&apos;s important that&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// we intercept changes to state so that we can create and add&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// a Domain Event to the &quot;observable subject&quot; when it&apos;s&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// appropriate to do so.&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;accepted&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// And then we create the domain event.&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDomainEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;OfferAcceptedEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;offerId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;accepted&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Already accepted this offer&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;declined&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Can&apos;t accept an offer already declined&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Offer was in an invalid state&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;declineOffer&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;offerState&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;initial&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Same deal is going on here.&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;declined&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDomainEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;OfferDeclinedEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;offerId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;accepted&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Already accepted this offer&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;declined&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Can&apos;t decline an offer already declined&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Offer was in an invalid state&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; OfferProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And if we were taking the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;use case approach&lt;/a&gt; of hooking this up, executing this feature would look like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AcceptOfferUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;AcceptOfferDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Offer&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; offerRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IOfferRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; artistRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IArtistRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;offerRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IOfferRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;offerRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; offerRepo
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AcceptOfferDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Offer&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; offerId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; offer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;offerRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;offerId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;offer &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Offer&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ErrorType&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NOT_FOUND&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Creates the domain event&lt;/span&gt;
    offer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;acceptOffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Persists the offer and dispatches all created domain events&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;offerRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;offer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Offer&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;offer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Because Domain Events are part of the domain, we&apos;ll always want to try to place Domain Events &lt;strong&gt;as close to the entities/aggregate roots as possible&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If we can trust that the domain layer will always generate the appropriate domain events in those key scenarios, we can enable several applications (perhaps deployed in separate bounded contexts and propagated over the network using a message queue like RabbitMQ) to implement their &lt;em&gt;own&lt;/em&gt; varying &lt;a href=&quot;/articles/enterprise-typescript-nodejs/application-layer-use-cases/&quot;&gt;application layer logic&lt;/a&gt; to handle these events however they please.&lt;/p&gt;
&lt;p&gt;For example, if our &lt;code class=&quot;language-text&quot;&gt;Billing&lt;/code&gt; subdomain were to subscribe to the &lt;code class=&quot;language-text&quot;&gt;OfferAcceptedEvent&lt;/code&gt;, we might want to fulfill the trade by facilitating the trade between the two parties and charging a 0.2% processing fee.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/domain-events/offer-accepted-event.svg&quot; alt=&quot;hi&quot;&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[No title]]></title><description><![CDATA[Originally published here June 2019, with discussions on Hackernews and Reddit.  Melvin Conway is credited with that quote back in 1967. In…]]></description><link>https://khalilstemmler.com/wiki/conways-law/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/conways-law/</guid><pubDate>Wed, 03 Jul 2019 04:05:26 GMT</pubDate><content:encoded>&lt;p&gt;Originally published here June 2019, with discussions on &lt;a href=&quot;https://news.ycombinator.com/item?id=20347821&quot;&gt;Hackernews&lt;/a&gt; and &lt;a href=&quot;https://www.reddit.com/r/programming/comments/c8sgdp/conways_law_domaindriven_design/&quot;&gt;Reddit&lt;/a&gt;. &lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Melvin Conway is credited with that quote back in 1967.&lt;/p&gt;
&lt;p&gt;In simple terms, Conway is saying:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;when we build software, we need to know the different groups/teams/roles it serves, and divide the app up  into separate parts, similar to how those groups normally communicate in real life&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That&apos;s the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;essence of the single responsibility principle&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Here are some reasons why it&apos;s incredibly relevant to a large number of topics on this blog.&lt;/p&gt;
&lt;h3 id=&quot;With-respect-to-domain-knowledge&quot; style=&quot;position:relative;&quot;&gt;With respect to domain knowledge&lt;a href=&quot;#With-respect-to-domain-knowledge&quot; aria-label=&quot;With respect to domain knowledge permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In &lt;a href=&quot;/articles/solid-principles/single-responsibility/&quot;&gt;this article&lt;/a&gt; about Domain Knowledge and the Single Responsibility principle, we agreed that &lt;em&gt;without having knowledge of the domain&lt;/em&gt;, it&apos;s incredibly hard to determine just how much responsibility a class and a module should have.&lt;/p&gt;
&lt;p&gt;Based on what Conway said back in 1967, if we&apos;re working on a system that&apos;s going to be used by groups of individuals in real life, like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Students&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Recruiters&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Interviewers&lt;/code&gt; in a recruitment platform or&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Accounting&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;HR&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Employees&lt;/code&gt; in a generic enterprise application&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;...then failure to understand which requirement maps to which group will make it difficult for us to identify when our classes or modules are responsible for too much (something that spills into multiple groups).&lt;/p&gt;
&lt;h3 id=&quot;With-respect-to-subdomains-and-boundaries&quot; style=&quot;position:relative;&quot;&gt;With respect to subdomains and boundaries&lt;a href=&quot;#With-respect-to-subdomains-and-boundaries&quot; aria-label=&quot;With respect to subdomains and boundaries permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In any large-scale application, the entire problem domain is the whole company.&lt;/p&gt;
&lt;p&gt;If we were to create Wal-Mart&apos;s online systems tomorrow, the entire problem domain is &lt;strong&gt;huge&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;One of the first few things we learn in software development is decomposition, breaking things to smaller modules. So we decompose the entire domain (Wal-Mart as a company) into subdomains.&lt;/p&gt;
&lt;p&gt;But how do we identify the subdomains?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conway&apos;s law&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;We split up the subdomains based on the organizational structure. So we need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an &lt;code class=&quot;language-text&quot;&gt;inventory&lt;/code&gt; subdomain so that people on the floor can keep track of everything that we currently have&lt;/li&gt;
&lt;li&gt;a &lt;code class=&quot;language-text&quot;&gt;time tracking&lt;/code&gt; subdomain for employees &lt;/li&gt;
&lt;li&gt;an &lt;code class=&quot;language-text&quot;&gt;accounting&lt;/code&gt; subdomain system for the accountants&lt;/li&gt;
&lt;li&gt;an &lt;code class=&quot;language-text&quot;&gt;HR / hiring&lt;/code&gt; subdomain system for HR and recruiters&lt;/li&gt;
&lt;li&gt;an &lt;code class=&quot;language-text&quot;&gt;ecommerce&lt;/code&gt; subdomain to sell things online&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;With-respect-updating-future-use-cases&quot; style=&quot;position:relative;&quot;&gt;With respect updating future use cases&lt;a href=&quot;#With-respect-updating-future-use-cases&quot; aria-label=&quot;With respect updating future use cases permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;From &quot;Head First Design Patterns&quot;, one of my favourite quotes is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;change is the only constant in software development&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Where does change originate from?&lt;/p&gt;
&lt;p&gt;Is it from within the code? Not really, unless we identify a memory leak or something.&lt;/p&gt;
&lt;p&gt;Is it from how we organized the code? It could be, if we didn&apos;t &lt;a href=&quot;/articles/name-construct-structure/&quot;&gt;organize our code&lt;/a&gt; well and suddenly it&apos;s hard to figure out where things are.&lt;/p&gt;
&lt;p&gt;Changes (feature requests) all originate from one place: the users using the software.&lt;/p&gt;
&lt;p&gt;If we&apos;ve organized our code by &lt;code class=&quot;language-text&quot;&gt;subdomain&lt;/code&gt; =&gt; &lt;code class=&quot;language-text&quot;&gt;use case&lt;/code&gt;, it makes the task of finding where to change code non-existent.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;  billing/
    └ useCases/
      └ getCustomerById/
        getAllCustomers/
        chargeCustomer/
        getCharges/
        refundCustomer/
        
  trading/
    └ useCases/
      └ approveOffer/
        getAllOffers/
        makeOffer/
        rejectOffer/
      
  catalog/
    └ useCases/
      └ addVinyl/
        getVinylById/
        getAllVinyl/
        updateVinyl/
        removeVinyl/
        search/

  users/
    └ useCases/
      └ createAccount/
        deleteAccount/
        login/
        logout/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If our logical boundaries between subdomains are healthy and dependencies to classes common between subdomains are carefully managed, changing a use case in one subdomain &lt;strong&gt;shouldnt&apos;t&lt;/strong&gt; affect a use case in another subdomain.&lt;/p&gt;
&lt;h3 id=&quot;Additional-reading&quot; style=&quot;position:relative;&quot;&gt;Additional reading&lt;a href=&quot;#Additional-reading&quot; aria-label=&quot;Additional reading permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Conway&amp;#x27;s_law&quot;&gt;Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[TypeScript & JavaScript Getters and Setters: Are they useless?]]></title><description><![CDATA[Join the discussions on Hackernews and Reddit. Getters and setters (also known as accessors) were introduced to JavaScript when ECMAScript…]]></description><link>https://khalilstemmler.com/blogs/typescript/getters-and-setters/</link><guid isPermaLink="false">https://khalilstemmler.com/blogs/typescript/getters-and-setters/</guid><pubDate>Mon, 01 Jul 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Join the discussions on &lt;a href=&quot;https://news.ycombinator.com/item?id=20357313&quot;&gt;Hackernews&lt;/a&gt; and &lt;a href=&quot;https://www.reddit.com/r/javascript/comments/c970dd/typescript_javascript_getters_and_setters_are/&quot;&gt;Reddit&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Getters and setters (also known as accessors) were introduced to JavaScript when ECMAScript 5 (2009) was released. &lt;/p&gt;
&lt;p&gt;The thing is, there&apos;s a lot of confusion about their utility and why you would ever even want to use them.&lt;/p&gt;
&lt;p&gt;I came across this &lt;a href=&quot;https://www.reddit.com/r/typescript/comments/87t1h7/are_getters_and_setters_an_antipattern/&quot;&gt;reddit thread&lt;/a&gt; where the discussion was about if they were an anti-pattern. &lt;/p&gt;
&lt;p&gt;Unfortunately, the general consensus of the thread was &quot;yes&quot;. I think that&apos;s because the majority of your front-end programming on a daily basis doesn&apos;t call for the utility that getters and setters offer.&lt;/p&gt;
&lt;p&gt;Though I disagree with getters and setters being an anti-pattern &lt;em&gt;overall&lt;/em&gt;. They have a lot of utility in several different cases.  &lt;/p&gt;
&lt;h2 id=&quot;What-are-they-for&quot; style=&quot;position:relative;&quot;&gt;What are they &lt;em&gt;for&lt;/em&gt;?&lt;a href=&quot;#What-are-they-for&quot; aria-label=&quot;What are they for permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Getters and setters are another way for you to provide access to the properties of an object.&lt;/p&gt;
&lt;p&gt;Trivial usage might look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ITrackProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Track&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ITrackProps&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;artist&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;artist&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ITrackProps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;play&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;	
	  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Playing &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; by &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The question becomes: &quot;why not just use regular class attributes?&quot;&lt;/p&gt;
&lt;p&gt;Well, in this case, &lt;em&gt;we could&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ITrackProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Track&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;play&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;	
	  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Playing &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; by &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&apos;s much simpler. And that&apos;s also a really simple use case. Let&apos;s look at scenarios that better describe why we might care about using getters and settters vs regular class attributes.&lt;/p&gt;
&lt;h2 id=&quot;Preventing-Anemic-Domain-models&quot; style=&quot;position:relative;&quot;&gt;Preventing Anemic Domain models&lt;a href=&quot;#Preventing-Anemic-Domain-models&quot; aria-label=&quot;Preventing Anemic Domain models permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Do you remember what an &lt;a href=&quot;/wiki/anemic-domain-model/&quot;&gt;anemic domain model&lt;/a&gt; is? One of the earliest ways to sniff out an anemic domain model is if there are getters and setters for &lt;strong&gt;every single attribute&lt;/strong&gt; of your domain entities (ie: &lt;em&gt;set&lt;/em&gt; operations that don&apos;t make sense to the domain-specific language are exposed). &lt;/p&gt;
&lt;p&gt;And if you don&apos;t explicitly use the &lt;code class=&quot;language-text&quot;&gt;get&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;set&lt;/code&gt; keywords, making everything &lt;code class=&quot;language-text&quot;&gt;public&lt;/code&gt; also has the same negative effect.&lt;/p&gt;
&lt;p&gt;Consider this example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Bad. You can now `set` the user id.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// When would you ever need to mutate a user&apos;s id to a&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// different identifier? Is that safe? Should you be able to?&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;constuctor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In Domain-Driven Design, to prevent an anemic domain model and push forward the creation of a domain-specific language it&apos;s &lt;u&gt;really&lt;/u&gt; important for us to &lt;em&gt;only expose operations that are valid to the domain&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;That means &lt;a href=&quot;/articles/solid-principles/single-responsibility/&quot;&gt;understanding the domain that you&apos;re working in&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&apos;ll put myself up for scrutiny. Let&apos;s take a look at the &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; class from &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;White Label&lt;/a&gt;, an open-source vinyl-trading app built with TypeScript using Domain-Driven Design.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AggregateRoot &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../core/domain/AggregateRoot&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../core/domain/UniqueEntityID&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Result &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../core/Result&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Artist &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./artist&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Genre &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./genre&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; TraderId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../trading/domain/traderId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Guard &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../core/Guard&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; VinylCreatedEvent &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./events/vinylCreatedEvent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; VinylId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./vinylId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  traderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TraderId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  dateAdded&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; VinylCollection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;VinylProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MAX_NUMBER_GENRES_PER_VINYL&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 🔥 1. Facade. The VinylId key doesn&apos;t actually exist&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// as a property of VinylProps, yet- we still need&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// to provide access to it.&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;vinylId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; VinylId &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; VinylId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 🔥 2. All of these properties are nested one layer&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// deep as props so that we can control access &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// and mutations to the ACTUAL values.&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;artist&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Artist &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;genres&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dateAdded&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Date &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dateAdded&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 🔥 3. You&apos;ll notice that there are no setters so far because &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// it doesn&apos;t make sense for us to be able to change any of these&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// things after it has been created&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;traderId&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TraderId &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;traderId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 🔥 4. This approach is called &quot;Encapsulate Collection&quot;. We&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// will need to add genres, yes. But we still don&apos;t expose the&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// setter because there&apos;s some invariant logic here that we want to&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ensure is enforced.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Invariants: &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// https://khalilstemmler.com/wiki/invariant/&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addGenre&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;genre&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maxLengthExceeded &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MAX_NUMBER_GENRES_PER_VINYL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; alreadyAdded &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;genre&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;alreadyAdded &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;maxLengthExceeded&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;genre&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 🔥 5. Provide a way to remove as well.&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;removeGenre&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;genre&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;g&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;genre&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; VinylProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 🔥 6. This is how we create Vinyl. After it&apos;s created, all properties &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// effectively become &quot;read only&quot;, except for Genre because that&apos;s all that&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// makes sense to enabled to be mutated.&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; VinylProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; propsResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;againstNullOrUndefinedBulk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;title&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;artist&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;genres&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; argument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;traderId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argumentName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;traderId&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;propsResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;succeeded&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;propsResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinyl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      dateAdded&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dateAdded &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dateAdded &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isNewlyCreated &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isNewlyCreated&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// 🔥 7. This is why we need VinylId. To provide the identifier&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// for any subscribers to this domain event.&lt;/span&gt;
      vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addDomainEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylCreatedEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Acting as a facade, maintaining readonly values, enforcing model expressiveness, encapsulating collections, AND &lt;a href=&quot;/blogs/domain-driven-design/where-do-domain-events-get-dispatched/&quot;&gt;creating domain events&lt;/a&gt; are some very solid use cases for getters and setters in &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Change-detection-in-Vuejs&quot; style=&quot;position:relative;&quot;&gt;Change detection in Vue.js&lt;a href=&quot;#Change-detection-in-Vuejs&quot; aria-label=&quot;Change detection in Vuejs permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://vuejs.org/v2/guide/reactivity.html&quot;&gt;Vue.js&lt;/a&gt;, one of the newer front-end frameworks, prides itself with being very fast and reactive.&lt;/p&gt;
&lt;p&gt;The reason why Vue.js does change detection so efficiently is because they use the &lt;code class=&quot;language-text&quot;&gt;Object.defineProperty()&lt;/code&gt; &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty&quot;&gt;API&lt;/a&gt; to &lt;em&gt;watch&lt;/em&gt; for changes to your View Models!&lt;/p&gt;
&lt;p&gt;From the Vue.js docs on Reactivity,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When you pass a plain JavaScript object to a Vue instance as its data option, Vue will walk through all of its properties and convert them to getter/setters using Object.defineProperty. The getter/setters are invisible to the user, but under the hood they enable Vue to perform dependency-tracking and change-notification when properties are accessed or modified. - &lt;a href=&quot;https://vuejs.org/v2/guide/reactivity.html&quot;&gt;Vue.js Docs: Reactivity&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;In conclusion, getters and setters &lt;em&gt;do&lt;/em&gt; have a lot of utility for a lot of different problems. Those problems just don&apos;t occur a whole lot in modern front-end web development.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Better Software Design with Application Layer Use Cases | Enterprise Node.js + TypeScript]]></title><description><![CDATA[The term Use Case is used to describe one of the potential ways that our software can be used. Another word that's sometimes used is feature…]]></description><link>https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/enterprise-typescript-nodejs/application-layer-use-cases/</guid><pubDate>Tue, 25 Jun 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;The term &lt;em&gt;Use Case&lt;/em&gt; is used to describe one of the potential ways that our software can be used.&lt;/p&gt;
&lt;p&gt;Another word that&apos;s sometimes used is &lt;em&gt;feature&lt;/em&gt;, though the concept is nearly identical.&lt;/p&gt;
&lt;p&gt;The whole purpose of building software is to &lt;u&gt;address one or more Use Cases&lt;/u&gt;. &lt;/p&gt;
&lt;p&gt;In large projects, it can sometimes be hard to determine what the capabilities of the system are. &lt;/p&gt;
&lt;p&gt;That&apos;s incredibly true on &lt;a href=&quot;/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;CRUD apps designed API-first&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What if there was a particular &lt;em&gt;construct&lt;/em&gt; that actually &lt;strong&gt;appeared&lt;/strong&gt; in our code that would &lt;strong&gt;describe&lt;/strong&gt; all of the different capabilities of our app?&lt;/p&gt;
&lt;p&gt;Something that would help towards encapsulating, organizing, and keeping track of all of the things that our application is capable of.&lt;/p&gt;
&lt;p&gt;Well, it &lt;em&gt;does&lt;/em&gt; exist, and it&apos;s properly called: &lt;em&gt;you guessed it&lt;/em&gt;, a &lt;strong&gt;Use Case&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;Clean Architecture&lt;/a&gt;, Use Cases are an &lt;strong&gt;application layer&lt;/strong&gt; concern that encapsulate the business logic involved in executing the features within our app(s).&lt;/p&gt;
&lt;p&gt;In this article, we&apos;ll cover the following topics towards structuring Node.js/TypeScript applications using Use Cases in the application layer:&lt;/p&gt;
&lt;ul class=&quot;aside&quot;&gt;
  &lt;li&gt;How to discover Use Cases&lt;/li&gt;
  &lt;li&gt;The role of the application layer&lt;/li&gt;
  &lt;li&gt;How to identify which subdomain Use Cases belong in&lt;/li&gt;
  &lt;li&gt;How Use Cases make large projects more readable (screaming architecture)&lt;/li&gt;
  &lt;li&gt;How to implement Use Cases with TypeScript&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To see the code used in this article, check out:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;https://github.com/stemmlerjs/white-label&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;Discovering-Use-Cases&quot; style=&quot;position:relative;&quot;&gt;Discovering Use Cases&lt;a href=&quot;#Discovering-Use-Cases&quot; aria-label=&quot;Discovering Use Cases permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are several different ways to plan out building an application. For a long time, I simply planned out how I would actually build something by designing the API first.&lt;/p&gt;
&lt;p&gt;Later on, I ended up moving more towards wire-framing and starting from the interface first, because the front-end would often dictate what&apos;s really needed and what&apos;s &lt;a href=&quot;/wiki/yagni/&quot;&gt;YAGNI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It wasn&apos;t until the projects I started working on got so complex that I realized I needed to take a more traditional approach to software planning: &lt;strong&gt;Use Case design&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Traditional-approach&quot; style=&quot;position:relative;&quot;&gt;Traditional approach&lt;a href=&quot;#Traditional-approach&quot; aria-label=&quot;Traditional approach permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There&apos;s a traditional approach to identifying and drawing Use Cases using a &lt;strong&gt;Use Case Diagram&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;In Use Case Diagrams, the stick-man represents an &lt;code class=&quot;language-text&quot;&gt;actor&lt;/code&gt; of our system (someone who uses it), and the circles represent all of the actual use cases that we&apos;d like to enable them to execute with our software.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/enterprise-node/use-cases/use-case-diagram-tra.png&quot; alt=&quot;Traditional Use Case Diagrams&quot;&gt;&lt;/p&gt;
&lt;p&gt;I think it&apos;s a good to know how to create these, but rarely do I ever start designing a system with the sole purpose of generating one of these documents. &lt;/p&gt;
&lt;p&gt;Instead, I try to identify the essential components through conversation and draw things out using a kind of free-form approach.&lt;/p&gt;
&lt;h3 id=&quot;Use-Case-Basics&quot; style=&quot;position:relative;&quot;&gt;Use Case Basics&lt;a href=&quot;#Use-Case-Basics&quot; aria-label=&quot;Use Case Basics permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The most important things to understand about identifying use cases are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ol&gt;
&lt;li&gt;Who the &lt;code class=&quot;language-text&quot;&gt;actors&lt;/code&gt; of the system are (who&apos;s executing the use cases)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;That use cases are either &lt;strong&gt;commands&lt;/strong&gt; or &lt;strong&gt;queries&lt;/strong&gt; &lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;That use cases belong to a particular &lt;strong&gt;subdomain&lt;/strong&gt; which may be deployed on separate &lt;strong&gt;bounded contexts&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;1-Actors&quot; style=&quot;position:relative;&quot;&gt;1. Actors&lt;a href=&quot;#1-Actors&quot; aria-label=&quot;1 Actors permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;It&apos;s easy to just call every &lt;code class=&quot;language-text&quot;&gt;actor&lt;/code&gt; a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;. We could do that, but it doesn&apos;t say much about the domain itself. &lt;/p&gt;
&lt;p&gt;There&apos;s a time and place to call a user a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;, like in an &lt;strong&gt;Identity &amp;#x26; Access Management&lt;/strong&gt; subdomain like Amazon IAM or Auth0, but we should try to be as expressive as we can about identifying the actual &lt;code class=&quot;language-text&quot;&gt;actors&lt;/code&gt; in our systems by thinking about their &lt;em&gt;role&lt;/em&gt; in the domain.&lt;/p&gt;
&lt;p&gt;Here are some alternatives to &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; depending on the domain:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A billing system: &lt;code class=&quot;language-text&quot;&gt;Customer&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Subscriber&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Accountant&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Treasurer&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Employee&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A blogging system: &lt;code class=&quot;language-text&quot;&gt;Editor&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Reviewer&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Guest&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Author&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A recruitment platform: &lt;code class=&quot;language-text&quot;&gt;JobSeeker&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Employer&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Interviewer&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Recruiter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Our vinyl-trading application: &lt;code class=&quot;language-text&quot;&gt;Trader&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Admin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;An email marketing company: &lt;code class=&quot;language-text&quot;&gt;Contact&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Recipient&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Sender&lt;/code&gt;,  &lt;code class=&quot;language-text&quot;&gt;ListOwner&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Get the point? &lt;strong&gt;Role&lt;/strong&gt; matters.&lt;/p&gt;
&lt;h4 id=&quot;2-Use-Cases-are-Commands-and-Queries&quot; style=&quot;position:relative;&quot;&gt;2. Use Cases are Commands and Queries&lt;a href=&quot;#2-Use-Cases-are-Commands-and-Queries&quot; aria-label=&quot;2 Use Cases are Commands and Queries permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;A Use Case will be either a &lt;strong&gt;command&lt;/strong&gt; or a &lt;strong&gt;query&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;There&apos;s an entire object-oriented design principle dedicated to this phenomenon called &lt;a href=&quot;/articles/oop-design-principles/command-query-segregation/&quot;&gt;CQS (Command-Query Segregation)&lt;/a&gt;. When you follow it, it helps to make application side-effects easier to reason about  and aids in reducing bugs and improving readability.&lt;/p&gt;
&lt;p&gt;For example, in our Vinyl-Trading app, &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;&quot;White Label&quot;&lt;/a&gt;, an example of a particular &lt;strong&gt;command&lt;/strong&gt; is to &lt;strong&gt;add vinyl to our wishlist&lt;/strong&gt;. That might appear in our code as a class called &lt;code class=&quot;language-text&quot;&gt;AddVinylToWishlist&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;An example of a &lt;strong&gt;query&lt;/strong&gt; would be to &lt;strong&gt;get our wishlist&lt;/strong&gt;, which might appear as &lt;code class=&quot;language-text&quot;&gt;GetWishlist&lt;/code&gt;.&lt;/p&gt;
&lt;p class=&quot;special-quote&quot;&gt;In &lt;b&gt;Command-Query Segregation&lt;/b&gt;, COMMANDS perform changes to the system &lt;b&gt;but return no value&lt;/b&gt;, and QUERIES pull data out of the system, &lt;b&gt;but produce no side effects&lt;/b&gt;.&lt;/p&gt;
&lt;h4 id=&quot;3-Use-cases-belong-to-a-particular-subdomain&quot; style=&quot;position:relative;&quot;&gt;3. Use cases belong to a particular &lt;strong&gt;subdomain&lt;/strong&gt;&lt;a href=&quot;#3-Use-cases-belong-to-a-particular-subdomain&quot; aria-label=&quot;3 Use cases belong to a particular subdomain permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Generally speaking, most applications are built up of &lt;em&gt;several&lt;/em&gt; subdomains.&lt;/p&gt;
&lt;p&gt;If you don&apos;t remember what a &lt;strong&gt;subdomain&lt;/strong&gt; from &lt;a href=&quot;/articles/categories/domain-driven-design&quot;&gt;domain-driven design&lt;/a&gt; is, it&apos;s a logical separation of the &lt;strong&gt;entire problem domain&lt;/strong&gt;. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A subdomain is a logical separation of the &lt;strong&gt;entire problem domain&lt;/strong&gt;. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What&apos;s the problem domain?&lt;/p&gt;
&lt;p&gt;For example, White Label, the Vinyl-Trading app that I&apos;m building, is about trading vinyl.&lt;/p&gt;
&lt;p&gt;But the problem domain isn&apos;t &lt;em&gt;only&lt;/em&gt; about enabling traders to trade vinyl. There&apos;s much more that needs to be accounted for. &lt;/p&gt;
&lt;p&gt;In addition to the trading aspect (&lt;code class=&quot;language-text&quot;&gt;Trading&lt;/code&gt;), the enterprise also has to account for several other subdomains: identity and access management (&lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt;), cataloging items (&lt;code class=&quot;language-text&quot;&gt;Catalog&lt;/code&gt;), billing (&lt;code class=&quot;language-text&quot;&gt;Billing&lt;/code&gt;), notifications and more.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/enterprise-node/use-cases/subdomains.svg&quot; alt=&quot;White Label subdomains&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is the essence of &lt;a href=&quot;/wiki/conways-law/&quot;&gt;Conway&apos;s Law&lt;/a&gt; which states:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Organizations that design systems, are constrained to produce designs that are copies of the communication structures of these organizations.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Conway&apos;s law actually helps answer a lot of questions like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how do we decide on our subdomains?&lt;/li&gt;
&lt;li&gt;how do we decide which subdomain a use case should belong to?&lt;/li&gt;
&lt;li&gt;how do we make it easier to change use cases in the future?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;For more on Conway&apos;s Law and how it can help make these decisions, check out &lt;a href=&quot;/wiki/conways-law/&quot;&gt;this article&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In any &lt;a href=&quot;/articles/categories/domain-driven-design&quot;&gt;domain-driven&lt;/a&gt; project, we&apos;re usually able to decompose the entire problem domain into separate subdomains; some of which are &lt;u&gt;essential&lt;/u&gt; that &lt;em&gt;we&lt;/em&gt; develop ourselves (like the &lt;code class=&quot;language-text&quot;&gt;Trading&lt;/code&gt; and probably &lt;code class=&quot;language-text&quot;&gt;Catalog&lt;/code&gt; subdomain), and some of which we might be able to just use a vendor (like Auth0 for &lt;code class=&quot;language-text&quot;&gt;Users &amp;amp; Identity&lt;/code&gt; or Stripe for &lt;code class=&quot;language-text&quot;&gt;Billing&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Large &lt;em&gt;monolith&lt;/em&gt; applications with minimal coupling between subdomains are said to be logically separate. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/enterprise-node/use-cases/folder-structure.png&quot; alt=&quot;White Label folder structure&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;caption&quot;&gt;A good start and a rule of thumb is to keep monolith project subdomains separate by folder. This improves readability as well (see &quot;&lt;a href=&quot;https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html&quot;&gt;Screaming Architecture&lt;/a&gt;&quot;).&lt;/div&gt;
&lt;p&gt;If our fictional enterprise application needed to scale out, that &lt;em&gt;logical&lt;/em&gt; separation would be &lt;strong&gt;essential&lt;/strong&gt; in order for us to &lt;em&gt;physically&lt;/em&gt; separate our problem domain into several &lt;u&gt;independently deployable units&lt;/u&gt;. &lt;/p&gt;
&lt;p&gt;In other words: microservices. &lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;/articles/categories/domain-driven-design&quot;&gt;DDD&lt;/a&gt;-lingo: separate &lt;strong&gt;bounded-contexts&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;We-discover-use-cases-through-conversation&quot; style=&quot;position:relative;&quot;&gt;We discover use cases through conversation&lt;a href=&quot;#We-discover-use-cases-through-conversation&quot; aria-label=&quot;We discover use cases through conversation permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A huge misconception about software development is that developers just code away in the corner and never have to talk to people. &lt;/p&gt;
&lt;p&gt;That&apos;s &lt;em&gt;so&lt;/em&gt; not true. So much of software development (especially in DDD) is consistently attempting to identify the correct language to effectively create a lasting software implementation of the model from real life.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Here&apos;s an example of the conversation to discover some of the Use Cases in White Label.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;So, I have this idea for an app. It&apos;s an app where you can trade vinyl with other people.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&quot;OK, cool. So like, Discogs?&quot;&lt;/p&gt;
&lt;p&gt;&quot;Yeah, pretty much. But it&apos;s only for vinyl. True hipsters.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Awesome, I like it. What if I don&apos;t want to trade my vinyl? Can I just &lt;em&gt;buy&lt;/em&gt; something?&quot;&lt;/p&gt;
&lt;p&gt;&quot;Yeah, let&apos;s say: you can either trade your own vinyl for someone elses, or you can &lt;em&gt;trade&lt;/em&gt; them money for it instead.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Oh, what about this? Users can make complex offers, like hey, I&apos;ll give you these 2 Devo albums, a Sex Pistols album and 60 bucks for that limited edition Birthday Party vinyl&quot;.&lt;/p&gt;
&lt;p&gt;&quot;Ah, so there&apos;s &lt;code class=&quot;language-text&quot;&gt;offers&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;trades&lt;/code&gt;. And an &lt;code class=&quot;language-text&quot;&gt;offer&lt;/code&gt; can include several records and/or money in exchange for one or more records. And the person who receives the offer can either accept it, or decline the offer.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Yeah, that sounds pretty accurate. And if they want to decline it, they can decline &apos;with comments&apos; or something, saying why they decline it, and give them another reason to make another offer.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Yeah ok cool.&quot;&lt;/p&gt;
&lt;p&gt;&quot;So what are the use cases we&apos;ve discovered so far?&quot;&lt;/p&gt;
&lt;p&gt;&quot;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;MakeOffer(offer: Offer)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;DeclineOffer(offerId: OfferId, comments?: string)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;AcceptOffer(offerId: OfferId)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&quot;&lt;/p&gt;
&lt;p&gt;&quot;Probably also the ability to &lt;em&gt;get&lt;/em&gt; all the offers, and &lt;em&gt;get&lt;/em&gt; an offer by id. We have to think about the UI as well. It&apos;s going to need some use cases.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Ah, yes. So also &lt;code class=&quot;language-text&quot;&gt;GetAllOffers(userId: User)&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;GetOfferById(offerId: OfferId)&lt;/code&gt;&quot;.&lt;/p&gt;
&lt;p&gt;&quot;Hmm, where did &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; come from?&quot;&lt;/p&gt;
&lt;p&gt;&quot;That&apos;s what we&apos;ve been talking about this whole time, no? Things &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt; can do.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Yeah, but not really. Let&apos;s think about the &lt;a href=&quot;https://www.google.com/search?q=ubiquitous+language&amp;#x26;oq=ubiquitous+language&amp;#x26;aqs=chrome..69i57.6981j0j7&amp;#x26;sourceid=chrome&amp;#x26;ie=UTF-8&quot;&gt;Ubiquitous Language&lt;/a&gt; here. With respect to this &lt;code class=&quot;language-text&quot;&gt;Trading&lt;/code&gt; subdomain and their &lt;em&gt;role&lt;/em&gt;, it would make more sense to call them &lt;code class=&quot;language-text&quot;&gt;Traders&lt;/code&gt;, or &lt;code class=&quot;language-text&quot;&gt;RecordCollectors&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&quot;Ahh, I see, the term &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; probably belongs more in a &lt;code class=&quot;language-text&quot;&gt;Users &amp;amp; Identity&lt;/code&gt; subdomain, not a... &lt;code class=&quot;language-text&quot;&gt;Trading&lt;/code&gt; subdomain, which is what we&apos;ve been discussing so far, right?&quot;&lt;/p&gt;
&lt;p&gt;&quot;Yeah, that&apos;s right.&quot;&lt;/p&gt;
&lt;p&gt;&quot;OK, let&apos;s go with &lt;code class=&quot;language-text&quot;&gt;Traders&lt;/code&gt;.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Awesome. So far, in the &lt;code class=&quot;language-text&quot;&gt;Trading&lt;/code&gt; subdomain, the Use Cases we have are: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;MakeOffer(offer: Offer)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;DeclineOffer(offerId: OfferId, comments?: string)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;AcceptOffer(offerId: OfferId)&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;GetAllOffers(traderId: TraderId)&lt;/code&gt; and&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;GetOfferById(offerId: offerId)&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I can&apos;t think of anything else yet.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Me neither, let&apos;s go with that for now.&quot;&lt;/p&gt;
&lt;p&gt;&quot;And it looks like we&apos;ve identified some of the Entities as well. &lt;code class=&quot;language-text&quot;&gt;Offer&lt;/code&gt;  and &lt;code class=&quot;language-text&quot;&gt;Trader&lt;/code&gt;, right?&quot;&lt;/p&gt;
&lt;p&gt;&quot;Yeah, &lt;code class=&quot;language-text&quot;&gt;Offer&lt;/code&gt; is probably going to be an Aggregate Root for all of the &lt;code class=&quot;language-text&quot;&gt;OfferItems&lt;/code&gt; as well (a collection of money + vinyl). We can figure that out later. Sounds good so far.&lt;/p&gt;
&lt;p&gt;&quot;Oh, and since we brought up the &lt;code class=&quot;language-text&quot;&gt;Users &amp;amp; Identity&lt;/code&gt; subdomain, should we address that as well?&quot;&lt;/p&gt;
&lt;p&gt;&quot;Eh, yeah- we could. It&apos;s probably going to be the same as every other app.&quot;&lt;/p&gt;
&lt;p&gt;&quot;What do you mean?&quot;&lt;/p&gt;
&lt;p&gt;&quot;Well, the use cases are pretty common. There&apos;s normally like something like: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;login(userEmail: UserEmail, password: UserPassword)&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;logout(authToken: JWTToken)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;verifyEmail(emailVerificationToken: EmailVerificationToken)&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;changePassword(passwordResetToken: Token, password: UserPassword)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You know what I mean? You&apos;ve probably done this plenty of times.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Ah, isn&apos;t that something we could probably outsource?&quot;&lt;/p&gt;
&lt;p&gt;&quot;Yeah, we could probably try &lt;a href=&quot;https://auth0.com/&quot;&gt;Auth0&lt;/a&gt; for that.&quot;&lt;/p&gt;
&lt;p&gt;&quot;What do they call that in DDD-lingo, again? The type of subdomain...&quot;&lt;/p&gt;
&lt;p&gt;&quot;A generic subdomain.&quot;&lt;/p&gt;
&lt;p&gt;&quot;Meaning?&quot;&lt;/p&gt;
&lt;p&gt;&quot;Meaning while it &lt;em&gt;might&lt;/em&gt; be a critical part of the business, yeah, it&apos;s not the &lt;em&gt;core&lt;/em&gt; of the business. The core is probably going to be the &lt;code class=&quot;language-text&quot;&gt;Trading&lt;/code&gt; subdomain&quot;.&lt;/p&gt;
&lt;p&gt;&quot;Right. That&apos;ll be the &lt;strong&gt;core&lt;/strong&gt; subdomain because that&apos;s essentially the &lt;em&gt;unique&lt;/em&gt; thing about our app that can&apos;t just be outsourced or bought off the shelf.&quot;&lt;/p&gt;
&lt;h2 id=&quot;The-role-of-the-Application-Layer&quot; style=&quot;position:relative;&quot;&gt;The role of the Application Layer&lt;a href=&quot;#The-role-of-the-Application-Layer&quot; aria-label=&quot;The role of the Application Layer permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you&apos;ve been following the series on &lt;a href=&quot;/articles/categories/enterprise-node-type-script&quot;&gt;Enterprise Node.js + TypeScript&lt;/a&gt;, you&apos;ll recall that the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;Domain Layer&lt;/a&gt; holds all of the &lt;a href=&quot;/articles/typescript-domain-driven-design/entities/&quot;&gt;entities&lt;/a&gt;, &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;value objects&lt;/a&gt;, has 0 dependencies to outer layers, and is the &lt;em&gt;first&lt;/em&gt; place that we aim to place business logic, especially if it pertains to one particular entity.&lt;/p&gt;
&lt;p&gt;For example, in White Label, if I were trying to figure out where to place &lt;a href=&quot;/wiki/invariant/&quot;&gt;invariant logic&lt;/a&gt; that would ensure that a &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; can only have up to at max 3 different &lt;code class=&quot;language-text&quot;&gt;Genre&lt;/code&gt;s, &lt;em&gt;that logic&lt;/em&gt; would belong in the &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; class (which is an &lt;strong&gt;aggregate root&lt;/strong&gt;).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vinyl&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AggregateRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;VinylProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;addGenre&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;genre&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MAX_NUMBER_OF_GENRES_PER_VINYL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Max number of genres reached&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;genreAlreadyExists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;genre&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;genres&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;genre&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;caption&quot;&gt;Ensuring domain model integrity by placing validation logic within the model itself.&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; is one of many domain models from the &lt;strong&gt;Domain Layer&lt;/strong&gt; from the &lt;code class=&quot;language-text&quot;&gt;Catalog&lt;/code&gt; subdomain.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/enterprise-node/use-cases/catalog-subdomain.svg&quot; alt=&quot;Catalog subdomain from our Vinyl-Trading app&quot;&gt;&lt;/p&gt;
&lt;p&gt;OK, so we generally understand what the Domain layer is for. And we remember that the &lt;strong&gt;infrastructure layer&lt;/strong&gt; contains external services and things that we don&apos;t want to muddy our inner layers with (controllers, databases, caches, etc).&lt;/p&gt;
&lt;p&gt;So then, what&apos;s the role of the &lt;strong&gt;application layer&lt;/strong&gt;?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The application layer contains the &lt;strong&gt;Use Cases&lt;/strong&gt; for a &lt;strong&gt;particular subdomain&lt;/strong&gt; in our application.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The use cases describe the &lt;em&gt;features&lt;/em&gt; of the &lt;strong&gt;application&lt;/strong&gt;, which may be independently deployed or deployed as a monolith. &lt;/p&gt;
&lt;p&gt;That means that when we put the use cases directly into a subdomain, we can understand the capabilities of that subdomain right away.&lt;/p&gt;
&lt;p&gt;In DDD-lingo, Use Cases are the &lt;strong&gt;application services&lt;/strong&gt;. They&apos;re responsible for retrieving the domain entities in addition to the information that they need in order to execute some domain logic.&lt;/p&gt;
&lt;p&gt;For example, in the &lt;code class=&quot;language-text&quot;&gt;AcceptOffer(offerId: OfferId)&lt;/code&gt; use case, all I have is the &lt;code class=&quot;language-text&quot;&gt;OfferId&lt;/code&gt;. That&apos;s not enough for me to do the &lt;em&gt;accept&lt;/em&gt; action. I&apos;m going to need the entire &lt;code class=&quot;language-text&quot;&gt;offer&lt;/code&gt; entity in order to save &lt;code class=&quot;language-text&quot;&gt;offer.accept()&lt;/code&gt; and dispatch a &lt;code class=&quot;language-text&quot;&gt;OfferAcceptedEvent&lt;/code&gt; domain event. To get the &lt;code class=&quot;language-text&quot;&gt;offer&lt;/code&gt;, I&apos;ll need to use a &lt;strong&gt;repository&lt;/strong&gt; to retrieve &amp;#x26; save it. &lt;em&gt;That&apos;s&lt;/em&gt; how they&apos;re responsible for retrieving and spinning up an execution environment with domain entities.&lt;/p&gt;
&lt;p&gt;Let&apos;s look at how we might structure a project around use cases.&lt;/p&gt;
&lt;h3 id=&quot;Structuring-projects-around-use-cases&quot; style=&quot;position:relative;&quot;&gt;Structuring projects around use cases&lt;a href=&quot;#Structuring-projects-around-use-cases&quot; aria-label=&quot;Structuring projects around use cases permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Uncle Bob identified a pattern called &quot;&lt;a href=&quot;https://www.google.com/search?q=screaming+architecture&amp;#x26;oq=screaming+architecture&amp;#x26;aqs=chrome..69i57.5406j0j7&amp;#x26;sourceid=chrome&amp;#x26;ie=UTF-8&quot;&gt;Screaming Architecture&lt;/a&gt;&quot;. It means that by just looking at the project structure itself, it should be figuratively &lt;em&gt;screaming&lt;/em&gt; at us: the &lt;strong&gt;type&lt;/strong&gt; of project we&apos;re working on, in addition to the capabilities of the system. &lt;/p&gt;
&lt;p&gt;Here&apos;s a little bit of what it looks like in White Label when we split it into &lt;code class=&quot;language-text&quot;&gt;Subdomain&lt;/code&gt; =&gt; &lt;code class=&quot;language-text&quot;&gt;Use Cases&lt;/code&gt; + &lt;code class=&quot;language-text&quot;&gt;entities&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/enterprise-node/use-cases/structured-around-use-cases.png&quot; alt=&quot;Projects are structured around use cases and domain models&quot;&gt;&lt;/p&gt;
&lt;p&gt;At a glance, this tells us a &lt;em&gt;ton&lt;/em&gt; about what the &lt;code class=&quot;language-text&quot;&gt;users&lt;/code&gt; subdomain is and what it does, in addition to what the &lt;code class=&quot;language-text&quot;&gt;catalog&lt;/code&gt; subdomain is and what it does.&lt;/p&gt;
&lt;h2 id=&quot;A-Use-Case-interface&quot; style=&quot;position:relative;&quot;&gt;A Use Case interface&lt;a href=&quot;#A-Use-Case-interface&quot; aria-label=&quot;A Use Case interface permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use Cases are simple in principle. They have an optional request and response.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IRequest&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; IResponse&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IRequest&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IResponse&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; IResponse&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Employing the design principle of &quot;always programming to an interface and not an implementation&quot;, we can create an interface to represent a Use Case like this.&lt;/p&gt;
&lt;p&gt;Simple enough, right?&lt;/p&gt;
&lt;h2 id=&quot;Implementing-a-Use-Case&quot; style=&quot;position:relative;&quot;&gt;Implementing a Use Case&lt;a href=&quot;#Implementing-a-Use-Case&quot; aria-label=&quot;Implementing a Use Case permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&apos;s take a look at how we might implement this. Let&apos;s do the &lt;code class=&quot;language-text&quot;&gt;AddVinylToCatalogUseCase&lt;/code&gt; from the &lt;code class=&quot;language-text&quot;&gt;Catalog&lt;/code&gt; subdomain.&lt;/p&gt;
&lt;p&gt;First, we&apos;ll create the class and implement the interface, using &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt; for the Generic &lt;a href=&quot;/articles/typescript-domain-driven-design/repository-dto-mapper/&quot;&gt;DTOs (data transmission objects)&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddVinylToCatalogUseCase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Alright, so in order to update a &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt;, we need to provide everything necessary in order to &lt;strong&gt;create&lt;/strong&gt; it, in addition to the &lt;code class=&quot;language-text&quot;&gt;Trader&lt;/code&gt;&apos;s id that we&apos;re adding it to. &lt;/p&gt;
&lt;p&gt;Let&apos;s put all of that in the request DTO.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddVinylToCatalogUseCaseRequestDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  vinylName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  artistNameOrId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  traderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  genresArray&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddVinylToCatalogUseCase&lt;/span&gt; 
  &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;AddVinylToCatalogUseCaseRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    
  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AddVinylToCatalogUseCaseRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We&apos;re ready to actually implement the use case algorithm now. &lt;/p&gt;
&lt;p&gt;Since our &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; aggregate root class needs an actual instance of an &lt;code class=&quot;language-text&quot;&gt;Artist&lt;/code&gt;, we&apos;ll have to determine whether to retrieve the artist by &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt; or by &lt;code class=&quot;language-text&quot;&gt;artistName&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;If the request fails, we&apos;ll use our &lt;a href=&quot;/articles/enterprise-typescript-nodejs/handling-errors-result-class/&quot;&gt;result class&lt;/a&gt; to safely return an error, otherwise we&apos;ll use a &lt;code class=&quot;language-text&quot;&gt;VinylRepo&lt;/code&gt; to save the &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; to persistence. &lt;/p&gt;
&lt;p&gt;So we&apos;ll need to use &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;Dependency Injection&lt;/a&gt; to inject a &lt;code class=&quot;language-text&quot;&gt;VinylRepo&lt;/code&gt; and an &lt;code class=&quot;language-text&quot;&gt;ArtistRepo&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;We can include that as a dependency in the &lt;code class=&quot;language-text&quot;&gt;constructor&lt;/code&gt; for this class.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddVinylToCatalogUseCaseRequestDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  vinylName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  artistNameOrId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  traderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  genresArray&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddVinylToCatalogUseCase&lt;/span&gt; 
  &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;AddVinylToCatalogUseCaseRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; vinylRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; artistRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IArtistRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;vinylRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; artistRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IArtistRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; vinylRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; artistRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AddVinylToCatalogUseCaseRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Alright, now let&apos;s hook up the logic.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddVinylToCatalogUseCaseRequestDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  vinylName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  artistNameOrId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  traderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  genresArray&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddVinylToCatalogUseCase&lt;/span&gt; 
  &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UseCase&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;AddVinylToCatalogUseCaseRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; vinylRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; artistRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IArtistRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;vinylRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; artistRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IArtistRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; vinylRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; artistRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AddVinylToCatalogUseCaseRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; vinylName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; artistNameOrId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; traderId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; genresArray &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Artist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isArtistId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TextUtil&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isUUID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistNameOrId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isArtistId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      artist &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistNameOrId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      artist &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findByArtistName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistNameOrId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      artist &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Artist&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
        name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ArtistName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistNameOrId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; 
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinylOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinylName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      artist&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; artist&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      traderId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TraderId&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;traderId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinyl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; vinylOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&apos;s it! Now how do we hook this up to our application?&lt;/p&gt;
&lt;h2 id=&quot;Use-cases-are-infrastructure-layer-concern-agnostic&quot; style=&quot;position:relative;&quot;&gt;Use cases are infrastructure-layer concern agnostic&lt;a href=&quot;#Use-cases-are-infrastructure-layer-concern-agnostic&quot; aria-label=&quot;Use cases are infrastructure layer concern agnostic permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use Cases are agnostic to how we hook them up. &lt;/p&gt;
&lt;p&gt;As long as we can provide the inputs, they can execute &lt;strong&gt;commands&lt;/strong&gt; and &lt;strong&gt;queries&lt;/strong&gt; on our system.&lt;/p&gt;
&lt;p&gt;That means that they can be hooked up by Express.js &lt;code class=&quot;language-text&quot;&gt;controllers&lt;/code&gt; or any other external services from the &lt;strong&gt;infrastructure layer&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; BaseController &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../../infra/http/BaseController&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AddVinylToCatalogUseCase &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./CreateJobUseCase&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; DecodedExpressRequest &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../../../../domain/types&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AddVinylToCatalogUseCaseRequestDTO &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./AddVinylToCatalogUseCaseRequestDTO&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddVinylToCatalogUseCaseController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; useCase&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AddVinylToCatalogUseCase&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;useCase&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AddVinylToCatalogUseCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;useCase &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; useCase&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeImpl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; req &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;req &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; DecodedExpressRequest&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; traderId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;decoded&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; requestDetails &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; AddVinylToCatalogUseCaseRequestDTO&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; resultOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;useCase&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;requestDetails&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      traderId
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resultOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resultOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Use cases can &lt;strong&gt;also&lt;/strong&gt; be executed by &lt;em&gt;other Use Cases&lt;/em&gt; from within the &lt;strong&gt;application layer&lt;/strong&gt; as well (but not from the Domain-layer as per Uncle Bob&apos;s &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;Dependency Rule&lt;/a&gt;). And that&apos;s &lt;em&gt;really&lt;/em&gt; cool.&lt;/p&gt;
&lt;h2 id=&quot;Elegant-usage-of-Use-Case-with-Domain-Events&quot; style=&quot;position:relative;&quot;&gt;Elegant usage of Use Case with Domain Events&lt;a href=&quot;#Elegant-usage-of-Use-Case-with-Domain-Events&quot; aria-label=&quot;Elegant usage of Use Case with Domain Events permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There&apos;s actually a really elegant way to &lt;strong&gt;chain&lt;/strong&gt; Use Cases together. &lt;/p&gt;
&lt;p&gt;You&apos;d want to chain Use Cases together when one event might &lt;u&gt;trigger&lt;/u&gt; another Use Case to be executed in certain scenarios. In Domain-Driven Design, we&apos;d identify this behaviour through an &lt;a href=&quot;https://philippe.bourgau.net/how-to-use-event-storming-to-introduce-domain-driven-design/&quot;&gt;Event storming exercise&lt;/a&gt; and use the &lt;strong&gt;Observer pattern&lt;/strong&gt; to emit Domain Events.&lt;/p&gt;
&lt;h3 id=&quot;Notifying-traders-when-an-item-from-their-wishlist-is-added&quot; style=&quot;position:relative;&quot;&gt;Notifying traders when an item from their wishlist is added&lt;a href=&quot;#Notifying-traders-when-an-item-from-their-wishlist-is-added&quot; aria-label=&quot;Notifying traders when an item from their wishlist is added permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In White Label, traders can add either &lt;code class=&quot;language-text&quot;&gt;artist&lt;/code&gt;s or specific &lt;code class=&quot;language-text&quot;&gt;vinyl&lt;/code&gt; to their &lt;code class=&quot;language-text&quot;&gt;wishlist&lt;/code&gt;. Whenever someone adds a new &lt;code class=&quot;language-text&quot;&gt;vinyl&lt;/code&gt; to their collection, traders that are interested in that particular &lt;code class=&quot;language-text&quot;&gt;vinyl&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;artist&lt;/code&gt; will be notified that it was posted. That way, they can make an &lt;code class=&quot;language-text&quot;&gt;offer&lt;/code&gt; to the owner for the &lt;code class=&quot;language-text&quot;&gt;vinyl&lt;/code&gt; that they&apos;re interested in.&lt;/p&gt;
&lt;p&gt;The following diagram is a simplification of the communication between layers and use cases. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/enterprise-node/use-cases/diagram.svg&quot; alt=&quot;Projects are structured around use cases and domain models&quot;&gt;&lt;/p&gt;
&lt;p&gt;At scale, if we wanted to deploy our subdomains as microservices instead of running it as a monolith in a single process, we could utilize a message broker like &lt;a href=&quot;https://www.rabbitmq.com/&quot;&gt;RabbitMQ&lt;/a&gt; or &lt;a href=&quot;https://aws.amazon.com/amazon-mq/&quot;&gt;Amazon MQ&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We&apos;ll follow up with the nitty-gritty on hooking up Domain Events to execute chained Use Cases in a de-coupled way using the observer pattern in a future article.&lt;/p&gt;
&lt;h2 id=&quot;Codebase&quot; style=&quot;position:relative;&quot;&gt;Codebase&lt;a href=&quot;#Codebase&quot; aria-label=&quot;Codebase permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;All the code in this article is from White Label, a Vinyl-Trading enterprise app built with Node.js + TypeScript using Domain-Driven Design. You can check it out on GitHub:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;https://github.com/stemmlerjs/white-label&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Implementing DTOs, Mappers & the Repository Pattern using the Sequelize ORM [with Examples] - DDD w/ TypeScript]]></title><description><![CDATA[Also from the Domain-Driven Design with TypeScript series. In Domain-Driven Design, there's a correct tool for every possible thing that…]]></description><link>https://khalilstemmler.com/articles/typescript-domain-driven-design/repository-dto-mapper/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/typescript-domain-driven-design/repository-dto-mapper/</guid><pubDate>Thu, 20 Jun 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;course-cta&quot;&gt;
We cover this topic in &lt;a href=&quot;https://www.essentialist.dev/master-the-essentials-of-software-design-with-typescript&quot;&gt;The Software Essentialist&lt;/a&gt; online course. Check it out if you liked this post.
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Also from the &lt;strong&gt;&lt;a href=&quot;/articles/categories/domain-driven-design/&quot;&gt;Domain-Driven Design with TypeScript&lt;/a&gt;&lt;/strong&gt; series&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In Domain-Driven Design, there&apos;s a &lt;em&gt;correct tool&lt;/em&gt; for every possible thing that needs to happen in the development of an object-modeled system.&lt;/p&gt;
&lt;p&gt;What&apos;s responsible for handling validation logic? &lt;em&gt;Value Objects&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Where do you handle handle domain logic? As close to the &lt;em&gt;Entity&lt;/em&gt; as possible, otherwise &lt;em&gt;domain services&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Perhaps one of the hardest aspects towards learning DDD is being able to determine &lt;em&gt;just what that tool is&lt;/em&gt; needed for the particular task.&lt;/p&gt;
&lt;p&gt;In DDD, the &lt;strong&gt;Repositories&lt;/strong&gt;, &lt;strong&gt;Data Mappers&lt;/strong&gt; and &lt;strong&gt;DTOs&lt;/strong&gt; are a &lt;a href=&quot;/articles/typescript-domain-driven-design/entities/&quot;&gt;critical part of the entity lifecycle&lt;/a&gt; that enable us to &lt;strong&gt;store&lt;/strong&gt;, &lt;strong&gt;reconsitute&lt;/strong&gt; and &lt;strong&gt;delete&lt;/strong&gt; domain entities.&lt;/p&gt;
&lt;p&gt;This type of logic is called &quot;&lt;em&gt;Data Access Logic&lt;/em&gt;&quot;.&lt;/p&gt;
&lt;p&gt;For developers coming from building &lt;a href=&quot;/articles/typescript-domain-driven-design/ddd-vs-crud-design/&quot;&gt;REST-ful CRUD APIs using MVC&lt;/a&gt; without much attention to encapsulating ORM data access logic, you&apos;ll learn:&lt;/p&gt;
&lt;ul class=&quot;aside&quot;&gt;
  &lt;li&gt;problems that occur when we don&apos;t encapsulate ORM data access logic&lt;/li&gt;
  &lt;li&gt;how DTOs can be used to stabilize an API&lt;/li&gt;
  &lt;li&gt;how Repositories act as a facade over complex ORM queries&lt;/li&gt;
  &lt;li&gt;approaches to creating repositories and&lt;/li&gt;
  &lt;li&gt;how Data Mappers can be used to translate to and from DTOs, Domain Entities and ORM models&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;How-do-we-usually-use-ORM-models-in-MVC-apps&quot; style=&quot;position:relative;&quot;&gt;How do we usually use ORM models in MVC apps?&lt;a href=&quot;#How-do-we-usually-use-ORM-models-in-MVC-apps&quot; aria-label=&quot;How do we usually use ORM models in MVC apps permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In a &lt;a href=&quot;/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;previous article about MVC&lt;/a&gt;, we looked at some of the most common approaches to utilizing ORMs like &lt;a href=&quot;http://docs.sequelizejs.com/&quot;&gt;Sequelize&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Take this simple &lt;code class=&quot;language-text&quot;&gt;controller&lt;/code&gt; where we create a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; User &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;201&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We agreed that the benefits of this approach were that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;this code is incredibly easy to read&lt;/li&gt;
&lt;li&gt;on small projects, this approach makes it easy to quickly become productive &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, as our applications grow and get more complex, this approach leads to several drawbacks &lt;em&gt;which may introduce bugs&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Summarizing &lt;a href=&quot;/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;what we spoke about last time&lt;/a&gt;, the main reason why it&apos;s problematic is because there&apos;s a &lt;u&gt;lack of a separation of concerns&lt;/u&gt;. This block of code is responsible for too many things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;handling the API request (&lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-consistent-expressjs-controllers/&quot;&gt;controller&lt;/a&gt; responsibility)&lt;/li&gt;
&lt;li&gt;performing validation on the domain object (not present here, but a &lt;a href=&quot;/articles/typescript-domain-driven-design/entities/&quot;&gt;domain entity&lt;/a&gt; or &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;value object&lt;/a&gt; responsibility)&lt;/li&gt;
&lt;li&gt;persisting a domain entity to the database (repository responsibility)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When we add more and more code to our project, it becomes really important that we pay attention to assigning &lt;a href=&quot;/articles/solid-principles/single-responsibility/&quot;&gt;singular responsibility&lt;/a&gt; to our classes. &lt;/p&gt;
&lt;h2 id=&quot;Scenario-Returning-the-same-view-model-in-3-separate-API-calls&quot; style=&quot;position:relative;&quot;&gt;Scenario: Returning the same view model in 3 separate API calls&lt;a href=&quot;#Scenario-Returning-the-same-view-model-in-3-separate-API-calls&quot; aria-label=&quot;Scenario Returning the same view model in 3 separate API calls permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&apos;s an example where lack of encapsulation towards how we &lt;strong&gt;retrieve data from ORMs&lt;/strong&gt; may lead to introducing bugs. &lt;/p&gt;
&lt;p&gt;Let&apos;s say we were working on our &lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;Vinyl Trading app&lt;/a&gt; and we&apos;re tasked with creating 3 different API calls.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;GET /vinyl?recent=6         - GET the 6 newest listed vinyl
GET /vinly/:vinylId/        - GET a particular vinyl by it&amp;#39;s id
GET /vinyl/owner/:userId/   - GET all vinyl owned by a particular user&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In each of these API calls, we need to return &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; view models &lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;So let&apos;s do the first controller: returning recent vinyl.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GetRecentVinylController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; models&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;models&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeImpl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Track&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Genre &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; count&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        include&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; owner&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Owner&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; attributes&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;user_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;display_name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Genres&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Track&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;TrackList&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        limit&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; count &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; count &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        order&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;created_at&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;DESC&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;OK. Not bad. If you&apos;re familiar with Sequelize, this is probably pretty standard for you.&lt;/p&gt;
&lt;p&gt;Now let&apos;s implement getting vinyl by its &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GetVinylById&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; models&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;models&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeImpl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Track&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Genre &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
          vinyl_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinylId
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        include&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Owner&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; attributes&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;user_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;display_name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Genres&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Track&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;TrackList&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Not too much is different between those two classes, eh? 😅&lt;/p&gt;
&lt;p&gt;So this is definitely not following the DRY principle, because we&apos;ve repeated a lot here.&lt;/p&gt;
&lt;p&gt;And you can expect that the 3rd API call is going to be somewhat similar to this.&lt;/p&gt;
&lt;p&gt;So far, the main problem that we&apos;re noticing is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;code duplication&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;While that&apos;s bad, because if we were to need to add a new &lt;em&gt;relationship&lt;/em&gt; to this model (like &lt;code class=&quot;language-text&quot;&gt;Label&lt;/code&gt;), we&apos;d have to &lt;em&gt;remember to&lt;/em&gt; scan through our code, locate each &lt;code class=&quot;language-text&quot;&gt;findOne()&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;findAll()&lt;/code&gt; for the &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; model, and add the new &lt;code class=&quot;language-text&quot;&gt;{ model: Label, as: &amp;#39;Label&amp;#39; }&lt;/code&gt; to our &lt;code class=&quot;language-text&quot;&gt;include&lt;/code&gt; array, it&apos;s not the worst aspect to this.&lt;/p&gt;
&lt;p&gt;There&apos;s another problem on the brewing on the horizon...&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Lack of data consistency&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Notice how we&apos;re passing back the ORM query results directly? &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&apos;s what&apos;s going back out to the client in response to the API calls.&lt;/p&gt;
&lt;p&gt;Well, what happens when we perform &lt;strong&gt;migrations&lt;/strong&gt;  on the database and add new columns? Worse- what happens when we remove a column or &lt;em&gt;change&lt;/em&gt; the name of a column?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We&apos;ve just broken the API for each client that depended on it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Hmm... we need a tool for this. &lt;/p&gt;
&lt;p&gt;Let&apos;s reach into our enterprise toolbox and see what we find...&lt;/p&gt;
&lt;p&gt;Ah, the &lt;strong&gt;DTO (Data Transfer Object)&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Data-Transfer-Objects&quot; style=&quot;position:relative;&quot;&gt;Data Transfer Objects&lt;a href=&quot;#Data-Transfer-Objects&quot; aria-label=&quot;Data Transfer Objects permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Data Transfer Objects are a (fancy) term for an &lt;strong&gt;object that carries data between two separate systems&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;When we&apos;re concerned with web development, we think of DTOs as &lt;strong&gt;View Models&lt;/strong&gt; because they&apos;re faux models. They&apos;re not really the REAL domain models, but they contain as much data that the view needs to know about.&lt;/p&gt;
&lt;p&gt;For example, the &lt;code class=&quot;language-text&quot;&gt;Vinyl&lt;/code&gt; view model / DTO could be built up to look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; Genre &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Post-punk&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Trip-hop&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Rock&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Rap&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Electronic&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Pop&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TrackDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  length&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; TrackCollectionDTO &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TrackDTO&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Vinyl view model / DTO, this is the format of the response&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  albumName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  label&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  country&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  yearReleased&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  artistName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  trackList&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TrackCollectionDTO&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The reason why this is so powerful is because we&apos;ve just &lt;u&gt;standardized our API response structure&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;Our DTO is a &lt;strong&gt;data contract&lt;/strong&gt;. We&apos;re telling anyone who uses this API, &quot;hey, this is going to be the format that you can always expect to see from this API call&quot;. &lt;/p&gt;
&lt;p&gt;Here&apos;s what I mean. Let&apos;s look at how we could use this in the example of retrieving Vinyl by id.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GetVinylById&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; models&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;models&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeImpl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Track&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Label &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        include&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Owner&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; attributes&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;user_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;display_name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Label&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Label&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Genres&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Track&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;TrackList&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Map the ORM object to our DTO&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dto&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; VinylDTO &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        albumName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;album_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        label&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Label&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        country&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Label&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;country&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        yearReleased&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;release_date&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFullYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Genres&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        artistName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        trackList&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TrackList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; t&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;album_track_number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; t&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;track_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          length&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; t&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;track_length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;// Using our baseController, we can specify the return type&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// for readability.&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;VinylDTO&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dto&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&apos;s great, but let&apos;s think about the responsibility of this class now.&lt;/p&gt;
&lt;p&gt;This is a &lt;code class=&quot;language-text&quot;&gt;controller&lt;/code&gt;, but it&apos;s responsible for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;defining the how to map persisted ORM models to &lt;code class=&quot;language-text&quot;&gt;VinylDTO&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;TrackDTO&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;Genres&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;defining just how much data needs to get retrieved from the Sequelize ORM call in order to successfully create the DTOs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&apos;s quite a bit more than &lt;code class=&quot;language-text&quot;&gt;controllers&lt;/code&gt; should be doing.&lt;/p&gt;
&lt;p&gt;Let&apos;s look into &lt;strong&gt;Repositories&lt;/strong&gt; and &lt;strong&gt;Data Mappers&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;We&apos;ll start with Repositories.&lt;/p&gt;
&lt;h2 id=&quot;Repositories&quot; style=&quot;position:relative;&quot;&gt;Repositories&lt;a href=&quot;#Repositories&quot; aria-label=&quot;Repositories permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As we mentioned earlier, the &lt;strong&gt;Repository&lt;/strong&gt; is a &lt;a href=&quot;/articles/typescript-domain-driven-design/entities/&quot;&gt;critical part of the entity lifecycle&lt;/a&gt; that enables us to &lt;strong&gt;store&lt;/strong&gt;, &lt;strong&gt;reconsitute&lt;/strong&gt; and &lt;strong&gt;delete&lt;/strong&gt; domain entities.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Repositories are Facades to persistence technologies (such as ORMs)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A &lt;strong&gt;Facade&lt;/strong&gt; is some design pattern lingo that refers to an object that provide a &lt;em&gt;simplified&lt;/em&gt; interface to a larger body of code. In &lt;em&gt;our&lt;/em&gt; case, that larger body of code is &lt;strong&gt;domain entity persistence&lt;/strong&gt; and  &lt;strong&gt;domain entity retrieval&lt;/strong&gt; logic.&lt;/p&gt;
&lt;h3 id=&quot;The-role-of-repositories-in-DDD--clean-architecture&quot; style=&quot;position:relative;&quot;&gt;The role of repositories in DDD &amp;#x26; clean architecture&lt;a href=&quot;#The-role-of-repositories-in-DDD--clean-architecture&quot; aria-label=&quot;The role of repositories in DDD  clean architecture permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In DDD &amp;#x26; clean architecture, repositories are &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;infrastructure-layer&lt;/a&gt; concerns.&lt;/p&gt;
&lt;p&gt;Generally speaking, we said that repos &lt;strong&gt;persist&lt;/strong&gt; and &lt;strong&gt;retrieve&lt;/strong&gt; domain entities.&lt;/p&gt;
&lt;h4 id=&quot;Persistence-objectives&quot; style=&quot;position:relative;&quot;&gt;Persistence objectives&lt;a href=&quot;#Persistence-objectives&quot; aria-label=&quot;Persistence objectives permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Scaffold complex persistence logic across &lt;a href=&quot;/articles/sequelize-tags-junction-pattern/&quot;&gt;junction&lt;/a&gt; and relationship tables.&lt;/li&gt;
&lt;li&gt;Rollback transactions that fail&lt;/li&gt;
&lt;li&gt;On &lt;code class=&quot;language-text&quot;&gt;save()&lt;/code&gt;, check if the entity already exists and then perform the create or update.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With respect to doing the &quot;create if not exists, else update&quot;, that&apos;s the type of complex data access logic that we don&apos;t want any other constructs in our domain to have to know about: only the repos should care about that.&lt;/p&gt;
&lt;h4 id=&quot;Retrieval-objectives&quot; style=&quot;position:relative;&quot;&gt;Retrieval objectives&lt;a href=&quot;#Retrieval-objectives&quot; aria-label=&quot;Retrieval objectives permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;We&apos;ve seen a little bit of this but the goals are ultimately to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Retrieve the entirety of data needed to create domain entities&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ie: we&apos;ve seen this with choosing what to &lt;code class=&quot;language-text&quot;&gt;include: []&lt;/code&gt; with Sequelize in order to create DTOs and Domain Objects.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Delegate the responsibility of &lt;em&gt;reconsituting&lt;/em&gt; entities to a &lt;code class=&quot;language-text&quot;&gt;Mapper&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Approaches-to-writing-repositories&quot; style=&quot;position:relative;&quot;&gt;Approaches to writing repositories&lt;a href=&quot;#Approaches-to-writing-repositories&quot; aria-label=&quot;Approaches to writing repositories permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There are several different approaches to creating repositories in your application. &lt;/p&gt;
&lt;h4 id=&quot;Generic-Repository-Interface&quot; style=&quot;position:relative;&quot;&gt;Generic Repository Interface&lt;a href=&quot;#Generic-Repository-Interface&quot; aria-label=&quot;Generic Repository Interface permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;You could create a generic repository interface, defining all kinds of common things that you&apos;d have to do to a model like &lt;code class=&quot;language-text&quot;&gt;getById(id: string)&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;save(t: T)&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;delete(t: T)&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Repo&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It&apos;s a good approach in the sense that we&apos;ve defined a common way for repositories to be created, but we might end up seeing the details of the data access layer leaking into calling code. &lt;/p&gt;
&lt;p&gt;The reason for that is because saying &lt;code class=&quot;language-text&quot;&gt;getById&lt;/code&gt; is feels like of &lt;em&gt;cold&lt;/em&gt;. If I was dealing with a &lt;code class=&quot;language-text&quot;&gt;VinylRepo&lt;/code&gt;, I&apos;d prefer to say &lt;code class=&quot;language-text&quot;&gt;getVinylById&lt;/code&gt; because it&apos;s a lot more descriptive to the &lt;strong&gt;Ubiquitous Language&lt;/strong&gt; of the domain. And if I wanted all the vinyl owned by a particular user, I&apos;d say &lt;code class=&quot;language-text&quot;&gt;getVinylOwnedByUserId&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;Having methods like &lt;code class=&quot;language-text&quot;&gt;getById&lt;/code&gt; is pretty &lt;a href=&quot;/wiki/yagni/&quot;&gt;YAGNI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That leads us into my preferred way to create repos.&lt;/p&gt;
&lt;h4 id=&quot;Repositories-by-entity--database-table&quot; style=&quot;position:relative;&quot;&gt;Repositories by entity / database table&lt;a href=&quot;#Repositories-by-entity--database-table&quot; aria-label=&quot;Repositories by entity  database table permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;I like being able to quickly add convience methods that make sense to the domain that I&apos;m working in, so I&apos;ll usually start with a slim &lt;strong&gt;base&lt;/strong&gt; repository:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Repo&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then extend that with additional methods that say more about the domain.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IVinylRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Repo&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getVinylById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;findAllVinylByArtistName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;VinylCollection&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getVinylOwnedByUserId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;VinylCollection&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;The reason why it&apos;s benefitial to always define repositories as interfaces first is because it adheres to the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;Liskov Subsitution Principle&lt;/a&gt; (which  enables concretions to be substituted), and it enables the concretions to be &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;Dependency Injected&lt;/a&gt; (think being able to mock a Sequelize Repo for a in-memory JSON one for unit tests)!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s go ahead and create a &lt;a href=&quot;/wiki/concrete-class/&quot;&gt;concrete class&lt;/a&gt; of our &lt;code class=&quot;language-text&quot;&gt;IVinylRepo&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Op &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;sequelize&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; IVinylRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./IVinylRepo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; VinylMap &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./VinyMap&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IVinylRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; models&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;models&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createQueryObject&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Track&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Label &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
      where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      include&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Owner&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; attributes&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;user_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;display_name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Label&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Label&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Genre&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Genres&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Track&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;TrackList&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; VinylModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; VinylModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
      where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; vinyl_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; VinylModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; VinylModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;destroy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
      where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; vinyl_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; VinylModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; exists &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rawVinylData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; VinylMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toPersistence&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;exists&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sequelizeVinyl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; VinylModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
        where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; vinyl_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; sequelizeVinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rawVinylData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// scaffold all of the other related tables (VinylGenres, Tracks, etc)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// If it fails, we need to roll everything back this.delete(vinyl);&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; VinylModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rawVinylData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getVinylById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; VinylModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; queryObject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createQueryObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    queryObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;where &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; vinyl_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinyl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; VinylModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryObject&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;vinyl &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; VinylMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findAllVinylByArtistName&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;artistName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;VinylCollection&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; VinylModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; queryObject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createQueryObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    queryObjectp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;where &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Op&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;like&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;artistName&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinylCollection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; VinylModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryObject&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; vinylCollection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;vinyl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; VinylMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getVinylOwnedByUserId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;VinylCollection&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; VinylModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Vinyl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; queryObject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createQueryObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    queryObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;include&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;where &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; user_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; userId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinylCollection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; VinylModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryObject&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; vinylCollection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;vinyl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; VinylMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See that we&apos;ve encapsulated our sequelize data access logic? We&apos;ve removed the need for repeatedly writing the &lt;code class=&quot;language-text&quot;&gt;include&lt;/code&gt;s because all ofthe &lt;strong&gt;required&lt;/strong&gt; include statements are here now.&lt;/p&gt;
&lt;p&gt;We&apos;ve also referred to a &lt;code class=&quot;language-text&quot;&gt;VinylMap&lt;/code&gt;. Let&apos;s take a quick look at the responsibility of a &lt;strong&gt;Mapper&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Data-Mappers&quot; style=&quot;position:relative;&quot;&gt;Data Mappers&lt;a href=&quot;#Data-Mappers&quot; aria-label=&quot;Data Mappers permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The responsibility of a &lt;strong&gt;Mapper&lt;/strong&gt; is to make all the transformations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;From Domain to DTO&lt;/li&gt;
&lt;li&gt;From Domain to Persistence&lt;/li&gt;
&lt;li&gt;From Persistence to Domain&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&apos;s what our &lt;code class=&quot;language-text&quot;&gt;VinylMap&lt;/code&gt; might look like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;VinylMap&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Mapper&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Vinyl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinylOrError &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      albumName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AlbumName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;album_name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      artistName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ArtistName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist_name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      tracks&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TrackList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; TrackMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinyl_id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; vinylOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; vinylOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toPersistence&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      album_name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;albumName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      artist_name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artistName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; VinylDTO &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      albumName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;albumName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      label&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Label&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      country&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Label&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;country&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value
      yearReleased&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;yearReleased&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      genres&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Genres&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      artistName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;aristName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      trackList&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vinyl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tracks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; TrackMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDTO&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;OK, now let&apos;s go back and refactor our controller from earlier using our &lt;code class=&quot;language-text&quot;&gt;VinylRepo&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;VinylMap&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GetVinylById&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; vinylRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IVinylRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;vinylRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IVinylRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylRepo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; vinylRepo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeImpl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; VinylRepo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinylId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vinylId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vinyl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Vinyl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; VinylRepo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getVinylById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinylId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dto&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; VinylDTO &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; VinylMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDTO&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vinyl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;VinylDTO&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dto&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Much. Cleaner. And. Singularly. Responsible.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this article, we took an in-depth look at &lt;strong&gt;DTOs&lt;/strong&gt;, &lt;strong&gt;Repositories&lt;/strong&gt; and &lt;strong&gt;Data Mappers&lt;/strong&gt; which all have their own single responsibility in the  infrastructure layer.&lt;/p&gt;
&lt;h3 id=&quot;The-actual-repo&quot; style=&quot;position:relative;&quot;&gt;The &lt;em&gt;actual&lt;/em&gt; repo&lt;a href=&quot;#The-actual-repo&quot; aria-label=&quot;The actual repo permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you&apos;d like to see some real life code, all of the code that was used in this article can be found in the my Vinyl Trading app (Node.js + TypeScript + Sequelize + Express) that I&apos;m working on for the upcoming DDD course. Check it out here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/stemmlerjs/white-label&quot;&gt;https://github.com/stemmlerjs/white-label&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p class=&quot;course-cta&quot;&gt;
We cover this topic in &lt;a href=&quot;https://www.essentialist.dev/master-the-essentials-of-software-design-with-typescript&quot;&gt;The Software Essentialist&lt;/a&gt; online course. Check it out if you liked this post.
&lt;/p&gt;
&lt;p&gt;&lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; View models are &lt;em&gt;essentially&lt;/em&gt; the same thing as DTOs (Data Transfer Objects).&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Domain Knowledge & Interpretation of the Single Responsibility Principle | SOLID Node.js + TypeScript]]></title><description><![CDATA[Is domain knowledge needed for the Single Responsibility Principle? TLDR; yes, we have to care enough to understand the domain in order to…]]></description><link>https://khalilstemmler.com/articles/solid-principles/single-responsibility/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/solid-principles/single-responsibility/</guid><pubDate>Thu, 13 Jun 2019 15:04:10 GMT</pubDate><content:encoded>&lt;div class=&quot;solid-book-cta course-cta&quot;&gt;
  &lt;div class=&quot;solid-book-logo-container&quot;&gt;
    &lt;img src=&quot;/img/resources/solid-book/book-logo.png&quot;/&gt;
  &lt;/div&gt;
  &lt;p&gt;This article is part of Solid Book - The Software Design &amp; Architecture Handbook w/ TypeScript + Node.js. &lt;a href=&quot;https://solidbook.io&quot;&gt;Check it out&lt;/a&gt; if you like this post.&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Is domain knowledge needed for the Single Responsibility Principle?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;TLDR; yes, we have to care enough to understand the domain in order to make smart design decisions.&lt;/p&gt;
&lt;p&gt;SRP is hands-down, the hardest principle from the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;SOLID Princples&lt;/a&gt; to understand because everyone has different interepretations of it.&lt;/p&gt;
&lt;p&gt;I&apos;m going to attempt to explain why understanding the domain can help you understand how to implement SRP.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;a--classanchor-nameDiscussionaDiscussion&quot; style=&quot;position:relative;&quot;&gt;&lt;a  class=&quot;anchor&quot; name=&quot;Discussion&quot;&gt;&lt;/a&gt;Discussion&lt;a href=&quot;#a--classanchor-nameDiscussionaDiscussion&quot; aria-label=&quot;a  classanchor nameDiscussionaDiscussion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In a recent discussion about the &lt;a href=&quot;/articles/software-professionalism/developer-principles/&quot;&gt;previous article&lt;/a&gt; on software design principles not being introduced to junior developers, one comment really struck a chord with me:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I would argue that SOLID on its own has a lot of esoteric nonsense packed in it, like what on earth even is single responsibility. Yeah and don&apos;t give me that &quot;one reason to change&quot; thing. It&apos;s meaningless unless you understand the domain (business wise) you&apos;re working in. And you can&apos;t understand the domain unless you actually have experience within the domain.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think “understanding the domain” is the &lt;em&gt;entirely the point&lt;/em&gt; of &lt;strong&gt;Single Responsibility Principle&lt;/strong&gt;. Understanding the domain is the only way that we can write code that is &lt;u&gt;singularly responsible&lt;/u&gt; for one thing.&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;guide to the SOLID principles&lt;/a&gt;, we said that SRP is defined as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;A class or function should only have one reason to change.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This means that we split code up &lt;strong&gt;based on the social structure&lt;/strong&gt; of the users using it. The example given was an application containing an HR department, an IT department, and an Accounting department that each needed to report their hours and calculate their pay.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Employee&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculatePay&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement algorithm for hr, accounting and it&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reportHours&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement algorithm for hr, accounting and it&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement algorithm for hr, accounting and it&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we realized that because the algorithms for each &lt;code class=&quot;language-text&quot;&gt;Employee&lt;/code&gt; might be &lt;em&gt;different&lt;/em&gt;, and change requests would likely come from each department, it would be dangerous to create and locate a single algorithm to be responsible for each of the different &lt;em&gt;actors&lt;/em&gt; (HR, IT and accounting) from a single class. &lt;/p&gt;
&lt;p&gt;We decided it was better to separate their algorithms.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Employee&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// This needs to be implemented&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculatePay&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// This needs to be implemented&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reportHours&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// let&apos;s assume THIS is going to be the &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// same algorithm for each employee- it can&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// be shared here.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// common save algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HR&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Employee&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;calculatePay&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement own algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;reportHours&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement own algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Accounting&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Employee&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;calculatePay&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement own algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;reportHours&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement own algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IT&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Employee&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is a good example. When we break up the algorithms from the &lt;code class=&quot;language-text&quot;&gt;Employee&lt;/code&gt; class into separate ones, we’ve potentially saved ourselves from the mess of trying to maintain 3 different algorithms (that might each independently be susceptible to change) in one class.&lt;/p&gt;
&lt;p&gt;The question is: how did we know that we needed to do that?&lt;/p&gt;
&lt;p&gt;How could we possibly have known that was a good thing to do?&lt;/p&gt;
&lt;p&gt;It’s because we’re &lt;u&gt;thinking about the domain&lt;/u&gt;.&lt;/p&gt;
&lt;h2 id=&quot;a--classanchor-nameSoftware-design-is-making-educated-guessesaSoftware-design-is-taking-an-educated-guess-at-the-future&quot; style=&quot;position:relative;&quot;&gt;&lt;a  class=&quot;anchor&quot; name=&quot;Software-design-is-making-educated-guesses&quot;&gt;&lt;/a&gt;Software design is taking an educated guess at the future&lt;a href=&quot;#a--classanchor-nameSoftware-design-is-making-educated-guessesaSoftware-design-is-taking-an-educated-guess-at-the-future&quot; aria-label=&quot;a  classanchor nameSoftware design is making educated guessesaSoftware design is taking an educated guess at the future permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Sometimes, I equate software design to playing midfield in soccer. As a midfielder, you have to be aware of what’s going on around you at all times. A good midfielder should at all times, be attempting to predict what’s going to happen 3 seconds in the future. &lt;/p&gt;
&lt;p&gt;A great midfielder is very perceptive to her surroundings, and will often be positioned on the field at a location that her teammates need her to be, even before they know they’re going to need her to be there.&lt;/p&gt;
&lt;p&gt;She’s able to identify &lt;strong&gt;if and when&lt;/strong&gt; her teammates are going to get blocked and pressured to pass the ball, so she positions herself to be available for that pass.&lt;/p&gt;
&lt;p&gt;Software design &amp;#x26; architecture is similar. We’re making best guesses (through abstractions and interfaces) at what we predict is going to need to happen in the future, without investing all of the upfront energy of implementing &lt;a href=&quot;/wiki/concrete-class/&quot;&gt;concretions&lt;/a&gt; of things we don’t need (&lt;a href=&quot;/wiki/yagni/&quot;&gt;YAGNI&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The only way for us to make those informed and educated design decisions? &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Understand the domain we’re working in&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If we don’t understand the domain we’re writing code in, we’re doomed to make &lt;a href=&quot;/articles/software-professionalism/developer-principles/&quot;&gt;expensive messes&lt;/a&gt;, because software requirements are &lt;strong&gt;sure&lt;/strong&gt; to change over time.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Therefore, I believe &lt;strong&gt;Single Responsibility&lt;/strong&gt; can be done correctly if &lt;strong&gt;you understand the domain&lt;/strong&gt;. Quite a bit of poor code I wrote during my early co-op roles originated from me from &lt;em&gt;not caring about understanding the domain&lt;/em&gt;, and just wanting to prove that I could write code that would work. &lt;/p&gt;
&lt;p&gt;Don’t be like me. Don’t be a code 🐵.&lt;/p&gt;
&lt;p&gt;The amount of time that you spend talking to domain experts, ramping up on understanding the domain, and asking questions is often related to the quality of the code that will come out of our capable hands.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;a--classanchor-nameAnother-SRP-Examplea-Is-this-code-singularly-responsible-to-you&quot; style=&quot;position:relative;&quot;&gt;&lt;a  class=&quot;anchor&quot; name=&quot;Another-SRP-Example&quot;&gt;&lt;/a&gt; Is this code singularly responsible to you?&lt;a href=&quot;#a--classanchor-nameAnother-SRP-Examplea-Is-this-code-singularly-responsible-to-you&quot; aria-label=&quot;a  classanchor nameAnother SRP Examplea Is this code singularly responsible to you permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I found this example Nodejs/JavaScript code on the internet and I wanted to talk about it. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; UserModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;models/user&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; EmailService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;services/email&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; NotificationService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;services/notification&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; Logger &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;services/logger&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;removeUserHandler&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; message &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Your account has been deleted&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; UserModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; UserModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; EmailService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; NotificationService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    Logger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;removeUserHandler&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Does this code say &lt;strong&gt;Single Responsibility&lt;/strong&gt; to you?&lt;/p&gt;
&lt;p&gt;At first, I thought &lt;strong&gt;no&lt;/strong&gt; because it has to utilize several different services that probably aren&apos;t related to the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; subdomain this code probably lives in. But then I thought about it some more.&lt;/p&gt;
&lt;h3 id=&quot;Almost&quot; style=&quot;position:relative;&quot;&gt;Almost&lt;a href=&quot;#Almost&quot; aria-label=&quot;Almost permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Almost, because after reading and understanding what this &lt;code class=&quot;language-text&quot;&gt;removeUserHandler&lt;/code&gt; &lt;code class=&quot;language-text&quot;&gt;use case&lt;/code&gt; &lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; adapter does, it appears to be responsible for 2 things.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;removing the user&lt;/strong&gt; &lt;em&gt;in addition to&lt;/em&gt; &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;all side effects of doing just that&lt;/strong&gt; (sending an email, notifying the user, logging when a failure happens).  &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Although it&apos;s not a &lt;strong&gt;single&lt;/strong&gt; responsibility, to me, it&apos;s a &lt;em&gt;fair&lt;/em&gt; delegation of responsibility. It would be nice to separate those two concerns, but if this isn&apos;t a very complicated application, I wouldn&apos;t push it.&lt;/p&gt;
&lt;p&gt;If tomorrow, my manager were to tell me: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Hey Khalil, I need you to make sure that after users get deleted, we also delete their image from Amazon S3&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I would know exactly where to add that code because there&apos;s &lt;u&gt;one place to change side effects of removing a user&lt;/u&gt;. Furthermore, the only &lt;em&gt;reason&lt;/em&gt; it would need to change is if we change the requirements of what happens after removing a user.&lt;/p&gt;
&lt;h4 id=&quot;Improving-it-with-Domain-Events-and-the-Observer-Pattern&quot; style=&quot;position:relative;&quot;&gt;Improving it with Domain Events and the Observer Pattern&lt;a href=&quot;#Improving-it-with-Domain-Events-and-the-Observer-Pattern&quot; aria-label=&quot;Improving it with Domain Events and the Observer Pattern permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Using Domain Events, we could actually dispatch a &lt;code class=&quot;language-text&quot;&gt;UserRemoved&lt;/code&gt; Domain Event from the &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt; subdomain and &lt;strong&gt;subscribe&lt;/strong&gt; to that event from the &lt;code class=&quot;language-text&quot;&gt;Email&lt;/code&gt; (and the same thing from the &lt;code class=&quot;language-text&quot;&gt;Notification&lt;/code&gt; &lt;u&gt;subdomains&lt;/u&gt;). &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/**
 * modules/email/subscriptions/AfterUserRemoved
 * This class resides within the Email subdomain (/modules/email)
 */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AfterUserRemoved&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IHandle&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserRemoved&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; emailService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IEmailService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;emailService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IEmailService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; emailService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;subscribeToDomainEvents&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    DomainEvents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;onUserRemoved&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; UserRemoved&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

 &lt;span class=&quot;token comment&quot;&gt;/**
  * @desc onUserRemoved, a handler for the UserRemoved domain event gets called
  * when the UserRemoved event is dispatched from the Users subdomain.
  * This is an example of the Observer pattern.
  * It&apos;s also how we can prevent &apos;God&apos;-classes that know about everything and
  * quickly become unmaintainable.
  */&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;onUserRemoved&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserRemoved&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; message &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Your account has been deleted&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This would remove the need for us to handle both &lt;em&gt;the actual removal of the user&lt;/em&gt; and the &lt;em&gt;side effects&lt;/em&gt; of doing so from the same class. &lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; The &lt;strong&gt;Observer pattern&lt;/strong&gt; is especially helpful here when there may be several side effects (against a particular domain event) across architectural boundaries.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;The truth is, understanding the domain improves our code by keeping responsibilities singular and focused at every level of the stack.&lt;/p&gt;
&lt;h2 id=&quot;Conclusion-design-improves-with-domain-enlightenment&quot; style=&quot;position:relative;&quot;&gt;Conclusion: design improves with domain enlightenment&lt;a href=&quot;#Conclusion-design-improves-with-domain-enlightenment&quot; aria-label=&quot;Conclusion design improves with domain enlightenment permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When we understand the domain, at an &lt;em&gt;architectural&lt;/em&gt; level:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;we’re able to implement &lt;strong&gt;package by module&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;we’re able to split out code into subdomains&lt;/li&gt;
&lt;li&gt;we’re able to identify how micro-services could be independently deployed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When we understand the domain, at the &lt;em&gt;module&lt;/em&gt; level:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;we’re able to identify when a block of code doesn’t belong in that particular subdomain / module and would be better suited in another one&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When we understand the domain, at a &lt;code class=&quot;language-text&quot;&gt;class&lt;/code&gt; level:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;we can understand if this block of code belongs in a helper/utility class or if it makes sense to stay in this class.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; In Uncle Bob&apos;s &quot;Clean Architecture&quot;, he talks about &lt;strong&gt;Use Cases&lt;/strong&gt; as one of the primary constructs in the &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;Clean Architecture&lt;/a&gt;. The Use Case is responsible for fetching entities from &lt;strong&gt;repositories&lt;/strong&gt;, executing business logic through &lt;strong&gt;domain services&lt;/strong&gt; and persisting those changes to the system with &lt;strong&gt;repositories&lt;/strong&gt;. Use Cases are flexible such that they&apos;re agnostic to the external infrastructure layer construct. This means you could hook them up to be used by &lt;strong&gt;Web Controllers&lt;/strong&gt; (for RESTful APIs), SOAP (if you needed to integrate with a legacy system), or any other type of protocol you could imagine. The most common usage is hooking them up to RESTful API controllers.&lt;/p&gt;
&lt;p&gt;&lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; If we were to go the event-driven approach with &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain Driven Design&lt;/a&gt;, initially identifying your project subdomains can difficult to figure out. &lt;/p&gt;
&lt;p&gt;There&apos;s a process called &lt;strong&gt;Event Storming&lt;/strong&gt; which enables you to figure out which events exist in your domain, and which &lt;strong&gt;aggregates&lt;/strong&gt; they belong to. This can help figure out what subdomains exist in your enterprise!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Over $85 billion spent on fixing bad code [bootcamps, junior devs, JavaScript, and software design principles]]]></title><description><![CDATA[I came across an article recently from CNBC titled Tech's ultimate success: Software developers are now more valuable to companies than…]]></description><link>https://khalilstemmler.com/articles/software-professionalism/developer-principles/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/software-professionalism/developer-principles/</guid><pubDate>Fri, 07 Jun 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;I came across an article recently from CNBC titled &lt;strong&gt;&lt;a href=&quot;https://www.cnbc.com/2018/09/06/companies-worry-more-about-access-to-software-developers-than-capital.html&quot;&gt;Tech&apos;s ultimate success: Software developers are now more valuable to companies than money&lt;/a&gt;&lt;/strong&gt;. They summarized a few really important details that I think are relevant to us today.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A majority of companies say lack of access to software developers is a bigger threat to success than lack of access to capital. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Truly, it’s a great time to be a software developer. We’re in demand. We’re essential to the success of a mass majority of companies. The fact is: &lt;u&gt;nearly every company is a software company&lt;/u&gt;. And every company needs good developers.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Still, companies are misusing their most important resource, with too many developers tied up in projects designed to prop up legacy systems and bad software, at a cost of $300 billion a year — $85 billion just dealing with bad code. Correctly deployed, the expertise of software developers could add $3 trillion to global GDP over the next decade. - CNBC (6 Sept. 2018)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;$85 billion. That’s a lot of money spent on maintaining &lt;strong&gt;bad software&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Think about if you hired someone to build your house. You would hope that for what you pay, you get what you’re paying for. You&apos;d also assume that you get the job done well, right?&lt;/p&gt;
&lt;p&gt;Building a house is not much different than building an application in principle. &lt;/p&gt;
&lt;p&gt;We need to pay just as much attention to the &lt;strong&gt;structure&lt;/strong&gt; &lt;em&gt;and&lt;/em&gt; the &lt;strong&gt;details&lt;/strong&gt; (or &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;Policy and Details&lt;/a&gt; with respect to code). Failing to do that, we could end up with something very expensive to fix. &lt;/p&gt;
&lt;p&gt;Bad situations like that can really hurt (and sometimes &lt;em&gt;end&lt;/em&gt;) companies. It&apos;s time we realize that &lt;strong&gt;we&apos;re software craftspeople&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;Yes, &lt;em&gt;it is important&lt;/em&gt; that we know how the tools work and how we can use them together. It’s also just as important that we have a &lt;strong&gt;strong set of software design principles&lt;/strong&gt;. A &lt;em&gt;professional code of quality&lt;/em&gt;. Something that we can refer back to will help us understand potentially bad (and expensive) code from good code.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Principles &gt; methodologies&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let&apos;s back it up a little bit.&lt;/p&gt;
&lt;h2 id=&quot;Where-does-all-this-bad-code-come-from&quot; style=&quot;position:relative;&quot;&gt;Where does all this bad code come from?&lt;a href=&quot;#Where-does-all-this-bad-code-come-from&quot; aria-label=&quot;Where does all this bad code come from permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I think there are a variety of reasons why we’re dealing with this as an industry now.&lt;/p&gt;
&lt;h3 id=&quot;a--classanchor-nameJavaScriptaJavaScript-is-the-superhero-that-it-never-wanted-to-be&quot; style=&quot;position:relative;&quot;&gt;&lt;a  class=&quot;anchor&quot; name=&quot;JavaScript&quot;&gt;&lt;/a&gt;JavaScript is the superhero that it never wanted to be&lt;a href=&quot;#a--classanchor-nameJavaScriptaJavaScript-is-the-superhero-that-it-never-wanted-to-be&quot; aria-label=&quot;a  classanchor nameJavaScriptaJavaScript is the superhero that it never wanted to be permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;/articles/javascript-vs-typescript/&quot;&gt;JavaScript&lt;/a&gt; has quickly become the most popular programming language on the planet. JavaScript itself, and the community are &lt;em&gt;amazing&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;What initially drew me to JavaScript years ago was the fact that you could not only create useful software, but you could create interesting web experiences. From web apps to desktop apps, mobile apps, backends, serverless functions, graphics, AR/VR, digital audio processing, artificial intelligence, etc. JS has quickly become one of &lt;strong&gt;the most sought after skills for developers&lt;/strong&gt; entering the industry.&lt;/p&gt;
&lt;p&gt;But also, in the most lovable way possible...&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;JavaScript is also kinda frankenstein.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Not only do JavaScript developers have to deal with the waltz of supporting non-modern browsers, but they&apos;ve also had to deal with the language going through various syntax extensions, flavours, and the rise of necessary build  / transpiling tools (hint hint, TypeScript), and frameworks. &lt;/p&gt;
&lt;p&gt;It’s a necessary strife though, because no one saw how important JavaScript was going to be. &lt;/p&gt;
&lt;h3 id=&quot;a--classanchor-nameBarriers-to-EntryaJavaScript-is-fun-and-the-barrier-to-entry-is-low-for-Junior-Developers&quot; style=&quot;position:relative;&quot;&gt;&lt;a  class=&quot;anchor&quot; name=&quot;Barriers-to-Entry&quot;&gt;&lt;/a&gt;JavaScript is fun and the barrier to entry is low for Junior Developers&lt;a href=&quot;#a--classanchor-nameBarriers-to-EntryaJavaScript-is-fun-and-the-barrier-to-entry-is-low-for-Junior-Developers&quot; aria-label=&quot;a  classanchor nameBarriers to EntryaJavaScript is fun and the barrier to entry is low for Junior Developers permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Despite the mess, JavaScript is &lt;strong&gt;fun&lt;/strong&gt; and producing something initially with JavaScript is a lot easier, thanks to the community ❤️ and the ecosystem.&lt;/p&gt;
&lt;p&gt;I think that’s why a lot of junior developers (myself included, at one time) flock to it. &lt;/p&gt;
&lt;p&gt;I don&apos;t know about you but I hated Java in school. Red lines in my NetBeans and constantly being unable to progress to the next lines of code because the types were wrong pissed me off.&lt;/p&gt;
&lt;p&gt;I hated that I had to define the type for everything. I hated the concept of generics and the fact that everything had to be a &lt;em&gt;class&lt;/em&gt;. It made no sense to me. It was very annoying for someone starting out. &lt;/p&gt;
&lt;p&gt;When I discovered JavaScript and the fact that you could make generative art, music, and a myriad of other interesting web experiences in JS just using &lt;em&gt;functions&lt;/em&gt;, I said &lt;em&gt;&quot;forget classes&quot;&lt;/em&gt; and went fully in on JavaScript.&lt;/p&gt;
&lt;p&gt;I was able to achieve a level of dexterity with JavaScript that I was never able to achieve with Java, way faster than I could have imagined.&lt;/p&gt;
&lt;p&gt;When I picked up my first JavaScript book from &lt;strong&gt;Scotch.io&lt;/strong&gt; titled “The MEAN Stack”, I flew through it. &lt;/p&gt;
&lt;p&gt;Following the code examples, I was amazed that I was now able to build a full-stack web app.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I’m a full-stack developer.” That’s what I began telling myself and everyone around me.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It wasn’t until much later in the future when I worked on large 120k+ line Node.js projects and even larger React.js ones (compiled without Types) that I realized there &lt;em&gt;might have been a reason why Java was so hard&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I was missing essential &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;software development &amp;#x26; design principles&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Because I didn’t spend any time honing that, I made a lot of expensive messes when I got put on real-life projects.&lt;/p&gt;
&lt;h3 id=&quot;a--classanchor-nameDesign-principlesaBootcamps-and-schools-are-ushering-developers-out-into-the-industry-with-a-lack-of-design-principles&quot; style=&quot;position:relative;&quot;&gt;&lt;a  class=&quot;anchor&quot; name=&quot;Design-principles&quot;&gt;&lt;/a&gt;Bootcamps and schools are ushering developers out into the industry with a lack of design principles&lt;a href=&quot;#a--classanchor-nameDesign-principlesaBootcamps-and-schools-are-ushering-developers-out-into-the-industry-with-a-lack-of-design-principles&quot; aria-label=&quot;a  classanchor nameDesign principlesaBootcamps and schools are ushering developers out into the industry with a lack of design principles permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Coding bootcamps have become really popular recently. They&apos;re arming their graduates with the skills in order to &lt;em&gt;write code that will work&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Unfortunately, some schools and bootcamps are failing to equip its graduates with best practices and design principles towards writing maintainable and flexible code.&lt;/p&gt;
&lt;p&gt;I think part of the reason this is happening is because developers are learning loosely typed languages like JavaScript, and some aspects of writing clean &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;SOLID code&lt;/a&gt;, like &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;Interface Segregation Principle&lt;/a&gt; are actually straight-up impossible with this language.&lt;/p&gt;
&lt;p&gt;For front-end developers, I think we can get away without this.&lt;/p&gt;
&lt;p&gt;But for anyone working with Node.js on the backend, I&apos;d say knowing your SOLID principles are a &lt;strong&gt;hard requirement&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Another &lt;strong&gt;bold&lt;/strong&gt; statement to make is that &lt;em&gt;if we understand the principles&lt;/em&gt;, we can vet new trends in the industry and &lt;u&gt;make educated software design choices for ourselves&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;For example, there&apos;s a lot of hype around React Hooks and their utility.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/developer-principles/hooks.png&quot; alt=&quot;react hooks and context replaces redux&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;via &lt;a href=&quot;https://www.instagram.com/p/Bx5aSqQgr7p/&quot;&gt;Tyler Mcginnis&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;Business are concerned with exactly two things:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Making money and saving money&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The ability to write code that is performant, clean, and able to be changed &lt;strong&gt;is so incredibly valuable to a business&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If we&apos;re writing code that is going to &lt;strong&gt;hard&lt;/strong&gt; or &lt;em&gt;impossible&lt;/em&gt; to be changed, then we&apos;re doing neither of those two things.&lt;/p&gt;
&lt;p&gt;A lot of companies talk about &lt;em&gt;Agile Software Development&lt;/em&gt; and say they practice it. Well, &lt;u&gt;flexibility&lt;/u&gt; is actually one of the primary requirements to doing Agile well.&lt;/p&gt;
&lt;h3 id=&quot;a--classanchor-nameAgileaAgile-requires-fundamental-software-design-skills&quot; style=&quot;position:relative;&quot;&gt;&lt;a  class=&quot;anchor&quot; name=&quot;Agile&quot;&gt;&lt;/a&gt;Agile requires fundamental software design skills&lt;a href=&quot;#a--classanchor-nameAgileaAgile-requires-fundamental-software-design-skills&quot; aria-label=&quot;a  classanchor nameAgileaAgile requires fundamental software design skills permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you’re not familiar with Agile, it’s an alternative approach to developing software that fosters &lt;strong&gt;iterative&lt;/strong&gt; improvements to code and detests a fully-fledged &lt;strong&gt;up-front design&lt;/strong&gt;. The contrasting approach is &lt;strong&gt;Waterfall&lt;/strong&gt; where you define everything upfront and stick to the script.&lt;/p&gt;
&lt;p&gt;The main reason why &lt;strong&gt;Agile&lt;/strong&gt; is such an attractive approach is because the iteration cycles are smaller. &lt;/p&gt;
&lt;p&gt;Because of this, we can &lt;em&gt;adapt&lt;/em&gt; to changes in project requirements (you can be 99.99% sure the requirements will be bound to change at some point).&lt;/p&gt;
&lt;p&gt;Here are a few principles of Agile Software Development.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deliver customer satisfaction by delivering valuable software continuously&lt;/li&gt;
&lt;li&gt;Always accept change of requirements no matter how early or late in the project&lt;/li&gt;
&lt;li&gt;Deliver software that works within a shorter timescale&lt;/li&gt;
&lt;li&gt;Working software is the key measure of progress&lt;/li&gt;
&lt;li&gt;The agile process promotes sustainable development&lt;/li&gt;
&lt;li&gt;Continuous attention to excellence and quality in technical development and design boosts the agility&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;from &lt;a href=&quot;https://luis-goncalves.com/what-is-agile-methodology/&quot;&gt;luis-goncalves.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So it&apos;s apparent that &lt;u&gt;knowing how to write maintainable and flexible code&lt;/u&gt; is incredibly important. &lt;/p&gt;
&lt;p&gt;Check.&lt;/p&gt;
&lt;p&gt;Makes sense. If you&apos;re a developer in 2019, you&apos;ll be doing Agile at some point. And if we&apos;re doing Agile, we can fully expect that the code is going to be going through a whole lot of &lt;strong&gt;changes and improvements&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;What do we call that in software development? The process of improving existing code? &lt;em&gt;Refactoring&lt;/em&gt;, right? &lt;/p&gt;
&lt;p&gt;The thing about refactoring code is that it’s &lt;strong&gt;incredibly risky&lt;/strong&gt; if we don’t have tests.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-dnt=&quot;true&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;You cannot refactor without a comprehensive suite of tests that you trust with your life.  If you have that suite, refactoring is always easy and free of risk.  A moment of refactoring becomes a trivial thing rather than a huge risk.&lt;/p&gt;&amp;mdash; Uncle Bob Martin (@unclebobmartin) &lt;a href=&quot;https://twitter.com/unclebobmartin/status/1135130426673106944?ref_src=twsrc%5Etfw&quot;&gt;June 2, 2019&lt;/a&gt;&lt;/blockquote&gt;


&lt;p&gt;Which leads me to my next observation.&lt;/p&gt;
&lt;h3 id=&quot;a--classanchor-nameTDDaDevelopers-struggle-with-writing-tests&quot; style=&quot;position:relative;&quot;&gt;&lt;a  class=&quot;anchor&quot; name=&quot;TDD&quot;&gt;&lt;/a&gt;Developers struggle with writing tests&lt;a href=&quot;#a--classanchor-nameTDDaDevelopers-struggle-with-writing-tests&quot; aria-label=&quot;a  classanchor nameTDDaDevelopers struggle with writing tests permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In a lot of Agile projects, tests don’t get written &lt;em&gt;at all&lt;/em&gt;. I know this because &lt;u&gt;I’ve been that developer not writing tests&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;I believe this is largely because a) developers are under a time constraint to meet the sprint, and don’t have time to write tests afterwards, and b) a lot of developers haven’t &lt;i&gt;actually been trained&lt;/i&gt; &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;how to write testable code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As Uncle Bob said, the blaring problem is that when no tests get written, it becomes incredibly risky to &lt;em&gt;refactor&lt;/em&gt; code later to add new features. &lt;/p&gt;
&lt;p&gt;It&apos;s even more risky if the &lt;em&gt;new&lt;/em&gt; features’ use cases cut through existing features. This can lead to a number of problems such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;large bodies of code that everyone is afraid to change&lt;/li&gt;
&lt;li&gt;a lack of encapsulation / anemic domain models&lt;/li&gt;
&lt;li&gt;non DRY code / repeated code (“helper” files and folders)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In Michael Feather’s book about dealing with Legacy Code, he says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Legacy code is code without tests”.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So let&apos;s put that to bed. It is risky as hell to change code without tests.&lt;/p&gt;
&lt;h3 id=&quot;TDD-Test-Driven-Development&quot; style=&quot;position:relative;&quot;&gt;TDD (Test-Driven Development)&lt;a href=&quot;#TDD-Test-Driven-Development&quot; aria-label=&quot;TDD Test Driven Development permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;One of the most controversial trends to hit the industry has been TDD. It’s worked for some, and failed for many others. But the reason I think it fails is because sometimes we try to treat TDD as &lt;u&gt;law&lt;/u&gt;.&lt;/p&gt;
&lt;h4 id=&quot;Fallacy-of-a-strict-Red-Green-Refactor-Loop&quot; style=&quot;position:relative;&quot;&gt;Fallacy of a strict Red-Green-Refactor Loop&lt;a href=&quot;#Fallacy-of-a-strict-Red-Green-Refactor-Loop&quot; aria-label=&quot;Fallacy of a strict Red Green Refactor Loop permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;In TDD, there’s a concept of a &lt;strong&gt;Red-Green-Refactor loop&lt;/strong&gt;. It goes like this.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Red&lt;/strong&gt;: Write a failing test&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Green&lt;/strong&gt;: Write the code to make the test pass&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Refactor&lt;/strong&gt;: Refactor the code when needed in order to improve the design.&lt;/p&gt;
&lt;p&gt;Don&apos;t treat this as a dogma. You don&apos;t have to execute TDD in this order to feel like you&apos;re doing it properly.&lt;/p&gt;
&lt;p&gt;That’s not important. You don’t have to stick to the loop by the letter. &lt;/p&gt;
&lt;p&gt;What’s important is that you write the tests &lt;em&gt;while you code&lt;/em&gt; &lt;em&gt;(or before you code)&lt;/em&gt; in order to reap the benefits of TDD.&lt;/p&gt;
&lt;p&gt;The primary benefit of doing this is that you know right away if your code is testable or not. And if it’s not, you can &lt;u&gt;take action right then and there&lt;/u&gt; before you pour some concrete that is going to be hard for yourself and anyone else to change in the future.&lt;/p&gt;
&lt;p&gt;Knowing how to write testable code can be taught. That’s one of the benefits of the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;SOLID principles&lt;/a&gt;, and it aims to address that.&lt;/p&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;developers aren’t being taught the essential software design skills&lt;/li&gt;
&lt;li&gt;lots of companies are practicing agile&lt;/li&gt;
&lt;li&gt;practicing agile means constantly changing and refactoring code&lt;/li&gt;
&lt;li&gt;to refactor code, we need tests&lt;/li&gt;
&lt;li&gt;to write tests, we need to know how to write testable code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Do you see what I see? The first step to addressing this problem in our industry starts with popularizing good software design skills with JavaScript.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In order to go fast, we need to go well.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[Clean Node.js Architecture | Enterprise Node.js + TypeScript]]></title><description><![CDATA[Have you ever heard of the "clean architecture"?  Maybe you've heard it by a different name... Clean Architecture, the Onion Architecture…]]></description><link>https://khalilstemmler.com/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/</guid><pubDate>Thu, 06 Jun 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;Have you ever heard of the &quot;clean architecture&quot;? &lt;/p&gt;
&lt;p&gt;Maybe you&apos;ve heard it by a different name...&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html&quot;&gt;Clean Architecture&lt;/a&gt;, the &lt;a href=&quot;https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/&quot;&gt;Onion Architecture&lt;/a&gt;, &lt;a href=&quot;http://www.dossier-andreas.net/software_architecture/ports_and_adapters.html&quot;&gt;Ports &amp;#x26; Adapters&lt;/a&gt;, &lt;a href=&quot;http://alistair.cockburn.us/Hexagonal+architecture&quot;&gt;Hexagonal Architecture&lt;/a&gt;, the Layered Architecture, DCI (Data, Context and Interaction), etc.&lt;/p&gt;
&lt;p&gt;They&apos;re all a little bit different in implementation, but for our understanding: they all mean the same thing.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Separation of concerns at the architectural level&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I first discovered the term when I read &quot;&lt;a href=&quot;https://www.amazon.ca/gp/product/0134494164/ref=as_li_tl?ie=UTF8&amp;#x26;tag=stemmlerjs09-20&amp;#x26;camp=15121&amp;#x26;creative=330641&amp;#x26;linkCode=as2&amp;#x26;creativeASIN=0134494164&amp;#x26;linkId=32995f69d0747d8723d42ffdda296878&quot;&gt;Clean Architecture&lt;/a&gt;&quot; by Robert C. Martin (Uncle Bob) (which, despite some negative reviews is actually an incredible read and I highly recommend you check it out).&lt;/p&gt;
&lt;p&gt;After reading his book and spending some time &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;learning the SOLID principles&lt;/a&gt;, not only did I enjoy the fact that the flexibilty and testability of my code improved, but I became &lt;em&gt;way more confident&lt;/em&gt; tackling &lt;u&gt;complex software development problems&lt;/u&gt; with TypeScript and Node.js.&lt;/p&gt;
&lt;p&gt;In this article, I&apos;ll cover:&lt;/p&gt;
&lt;ul class=&quot;aside&quot;&gt;
  &lt;li&gt;How the clean architecture separates the concerns of your code&lt;/li&gt;
  &lt;li&gt;How it enables you to write testable code&lt;/li&gt;
  &lt;li&gt;How it also enables you to write flexible code&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Understanding-the-Clean-Architecture&quot; style=&quot;position:relative;&quot;&gt;Understanding the Clean Architecture&lt;a href=&quot;#Understanding-the-Clean-Architecture&quot; aria-label=&quot;Understanding the Clean Architecture permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;Policy-vs-Detail&quot; style=&quot;position:relative;&quot;&gt;Policy vs. Detail&lt;a href=&quot;#Policy-vs-Detail&quot; aria-label=&quot;Policy vs Detail permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When we&apos;re writing code, at any given time, we&apos;re either writing &lt;strong&gt;Policy&lt;/strong&gt; or &lt;strong&gt;Detail&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/clean-architecture/policy-vs-detail.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Policy&lt;/strong&gt; is when we&apos;re specifying what should happen, and &lt;em&gt;when&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Policy&lt;/strong&gt; is mostly concerned with the business-logic, rules and abstractions that exist in the domain that we&apos;re coding in.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Detail&lt;/strong&gt; is when we specify &lt;em&gt;how&lt;/em&gt; the &lt;strong&gt;policy&lt;/strong&gt; happens.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Details&lt;/strong&gt; actually enforce the policy. &lt;strong&gt;Details&lt;/strong&gt; are implementations of the policy.&lt;/p&gt;
&lt;p&gt;An easy way to figure out if the code you&apos;re writing is &lt;em&gt;detail&lt;/em&gt; or &lt;em&gt;policy&lt;/em&gt; is to ask yourself:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;does this code enforce a rule about how something should work in my domain?&lt;/li&gt;
&lt;li&gt;or does this code simply &lt;em&gt;make something work&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For that reason: frameworks (like &lt;a href=&quot;https://nestjs.com/&quot;&gt;Nest.js&lt;/a&gt; and &lt;a href=&quot;https://expressjs.com/&quot;&gt;Express.js&lt;/a&gt;), npm libraries (like &lt;a href=&quot;https://lodash.com&quot;&gt;lodash&lt;/a&gt;, &lt;a href=&quot;https://rxjs-dev.firebaseapp.com/&quot;&gt;RxJs&lt;/a&gt; or &lt;a href=&quot;https://redux.js.org/&quot;&gt;Redux&lt;/a&gt;) &lt;u&gt;are details&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;Again,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The ultimate goal of the Clean Architecture is to separate Policy vs. Detail at the architectural level.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So let&apos;s see what that looks like:&lt;/p&gt;
&lt;h3 id=&quot;Layered-Architecture&quot; style=&quot;position:relative;&quot;&gt;Layered Architecture&lt;a href=&quot;#Layered-Architecture&quot; aria-label=&quot;Layered Architecture permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/clean-architecture/group.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Those small half-circles are meant to signify writing interfaces (at the policy level) to be implemented by the detail level&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This diagram is a sort of simplification of all of the other diagrams I found. There&apos;s more than just these two layers (read &quot;&lt;a href=&quot;/articles/software-design-architecture/organizing-app-logic/&quot;&gt;Organizing App Logic with the Clean Architecture&lt;/a&gt;&quot; for a more detailed depiction). But for our understanding of the concept, its much easier to think about a clean architecture like this.&lt;/p&gt;
&lt;p&gt;&lt;u&gt;So what does this mean?&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;In one layer (domain) we have all of the important stuff: the &lt;em&gt;entities&lt;/em&gt;, &lt;em&gt;business logic&lt;/em&gt;, &lt;em&gt;rules&lt;/em&gt; and &lt;em&gt;events&lt;/em&gt;. This is the &lt;u&gt;irreplaceable&lt;/u&gt; stuff in our software that we can&apos;t just swap out for another library or framework.&lt;/p&gt;
&lt;p&gt;The other layer (infra) contains everything that actually &lt;em&gt;spins up&lt;/em&gt; the code in the domain layer to execute.&lt;/p&gt;
&lt;p&gt;You&apos;ll recall that this is &lt;a href=&quot;/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/&quot;&gt;the biggest challenge in MVC&lt;/a&gt;, figuring out what the &quot;M&quot; should do and how it does it. Well, this is it. The &quot;M&quot; = that Domain Layer.&lt;/p&gt;
&lt;p&gt;Here&apos;s an illustration how a RESTful HTTP call might cause code to be executed across our entire architecture. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/clean-architecture/execution-cycle.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;There&apos;s a pattern here with respect to the &lt;u&gt;direction of dependencies&lt;/u&gt;.&lt;/p&gt;
&lt;h3 id=&quot;The-Dependency-Rule&quot; style=&quot;position:relative;&quot;&gt;The Dependency Rule&lt;a href=&quot;#The-Dependency-Rule&quot; aria-label=&quot;The Dependency Rule permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In Uncle Bob&apos;s book, he describes &lt;strong&gt;the dependency rule&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That rule specifies that something declared in an outer circle &lt;u&gt;must not be mentioned in the code by an inner circle&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;In other diagrams, there are many more layers. The rule still applies.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That means that code can only point inwards.&lt;/p&gt;
&lt;p&gt;Domain Layer code can&apos;t depend on Infrastructure Layer code.&lt;/p&gt;
&lt;p&gt;But Infrastructure Layer Code &lt;em&gt;can depend&lt;/em&gt; on Domain Layer code (because it goes inwards).&lt;/p&gt;
&lt;p&gt;When we follow this rule, we&apos;re essentially following the &lt;a href=&quot;dependency-inversion/&quot;&gt;Dependency Inversion&lt;/a&gt; rule from the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;SOLID Principles&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;Ports-and-Adapters-way-of-thinking-about-Clean-Architecture&quot; style=&quot;position:relative;&quot;&gt;Ports and Adapters way of thinking about Clean Architecture&lt;a href=&quot;#Ports-and-Adapters-way-of-thinking-about-Clean-Architecture&quot; aria-label=&quot;Ports and Adapters way of thinking about Clean Architecture permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;ports and adapters&lt;/strong&gt; approach to thinking about this is that the &lt;em&gt;interfaces&lt;/em&gt; and &lt;em&gt;abstract classes&lt;/em&gt; are the &lt;strong&gt;Ports&lt;/strong&gt; and the &lt;a href=&quot;/wiki/concrete-class/&quot;&gt;concrete classes&lt;/a&gt; (ie: the implementations) are the &lt;strong&gt;adapters&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Let&apos;s visualize it.&lt;/p&gt;
&lt;p&gt;Let&apos;s say I was to design an &lt;code class=&quot;language-text&quot;&gt;IEmailService&lt;/code&gt; interface. It specifies all of the things that an &lt;em&gt;Email Service&lt;/em&gt; can do. But it doesn&apos;t actually implement any of those things specifically.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IEmailService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mail&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IMail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IMailTransmissionResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here&apos;s my little &lt;strong&gt;Port&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/clean-architecture/email-service-1.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;And let&apos;s say I&apos;m just wiring up some code that relies on an &lt;code class=&quot;language-text&quot;&gt;IEmailService&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EmailNotificationsService&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IHandle&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;AccountVerifiedEvent&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; emailService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IEmailService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;emailService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IEmailService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    DomainEvents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onAccountVerifiedEvent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; AccountVerifiedEvent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;onAccountVerifiedEvent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AccountVerifiedEvent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    emailService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      to&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;me@khalilstemmler.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;You&apos;re in, my dude&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Because I&apos;m referring to &lt;strong&gt;policy&lt;/strong&gt;, all that&apos;s left to do is to create the &lt;strong&gt;implementation&lt;/strong&gt; (the details).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// We can define several valid implementations.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// This infra-layer code relies on the Domain layer email service.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MailchimpEmailService&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IEmailService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mail&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IMail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IMailTransmissionResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// alg&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SendGridEmailService&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IEmailService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mail&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IMail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IMailTransmissionResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// alg&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MailgunEmailService&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IEmailService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mail&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IMail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IMailTransmissionResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// alg&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/clean-architecture/email-service-2.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;When I go to hook this thing up, I have several options available now.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// index.js&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; EmailNotificationsService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./services/EmailNotificationsService&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; MailchimpEmailService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./infra/services/MailchimpEmailService&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; SendGridEmailService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./infra/services/SendGridEmailService&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; MailgunEmailService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./infra/services/MailgunEmailService&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mailChimpService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MailchimpEmailService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sendGridService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SendGridEmailService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mailgunService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MailgunEmailService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// I can pass in any of these since they are all valid IEmailServices&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EmailNotificationsService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mailChimpService&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Look! The port fits the adapter ❤️.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/clean-architecture/email-service-3.svg&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;a href=&quot;https://solidbook.io&quot;&gt;
  &lt;img src=&quot;/img/resources/solid-book/book-banner.png&quot;/&gt;
&lt;/a&gt;
&lt;p&gt;Hopefully we&apos;re starting to see how this can make our code more  &lt;strong&gt;testable&lt;/strong&gt; and &lt;strong&gt;flexible&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Code-is-testable&quot; style=&quot;position:relative;&quot;&gt;Code is testable&lt;a href=&quot;#Code-is-testable&quot; aria-label=&quot;Code is testable permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you follow the dependency rule, domain layer code has 0 dependencies.&lt;/p&gt;
&lt;p&gt;You know what that means? &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We can actually test it&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Next time you&apos;re writing code, think about it like this...&lt;/p&gt;
&lt;p&gt;Before you get too far along working on some classes, ask yourself: &quot;can I &lt;em&gt;mock&lt;/em&gt; what I just wrote?&quot;&lt;/p&gt;
&lt;p&gt;If you were following &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;SOLID&lt;/a&gt; and referring to &lt;strong&gt;interfaces&lt;/strong&gt; or &lt;strong&gt;abstract classes&lt;/strong&gt;, the answer will be &lt;em&gt;yes&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If you&apos;ve been referring to concretions, it&apos;ll be considerably more challenging to write tests for it. This is caused by &lt;a href=&quot;/wiki/dependency-inversion/&quot;&gt;coupling&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Code-is-flexible&quot; style=&quot;position:relative;&quot;&gt;Code is flexible&lt;a href=&quot;#Code-is-flexible&quot; aria-label=&quot;Code is flexible permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When we&apos;ve separated the concerns between Policy and Detail, we create an explicit relationship that we know how to deal with.&lt;/p&gt;
&lt;p&gt;If we change the policy, we &lt;em&gt;might&lt;/em&gt; end up affecting the detail (since detail depends on policy).&lt;/p&gt;
&lt;p&gt;But if we change the detail, it should &lt;u&gt;never affect the policy&lt;/u&gt; because policy doesn&apos;t depend on detail.&lt;/p&gt;
&lt;p&gt;This separation of concerns, combined with adhering to the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;SOLID&lt;/a&gt; principles makes changing code a lot easier.&lt;/p&gt;
&lt;h3 id=&quot;Tests&quot; style=&quot;position:relative;&quot;&gt;Tests?&lt;a href=&quot;#Tests&quot; aria-label=&quot;Tests permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The only way we can be certain about changing code is to have written tests for it. &lt;/p&gt;
&lt;p&gt;Domain code is incredibly easy to test (since it has 0 dependencies) and refers to abstractions. We can really easily create mocks for things by implementing the interface with our mock classes.&lt;/p&gt;
&lt;p&gt;Infrastructure layer code is a little bit more challenging (and slower) to test because it has dependencies (web servers, caches, key-value object stores like Redis, etc).&lt;/p&gt;
&lt;h2 id=&quot;Too-clean&quot; style=&quot;position:relative;&quot;&gt;Too clean?&lt;a href=&quot;#Too-clean&quot; aria-label=&quot;Too clean permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The more complex the software you&apos;re building, and the more robust it needs to be, the &lt;u&gt;more you need to build into it, the mechanisms for flexibility&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;For example: if you&apos;re writing a quick Node.js script to scrape a particular web page periodically so that you can automate something, &lt;strong&gt;don&apos;t spend &lt;em&gt;too much time&lt;/em&gt; trying to make your code SOLID&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;But, if you&apos;re building a web scraper that needs to &lt;em&gt;know how to scrape all of the 100 most popular job boards in the world&lt;/em&gt;, then you might want to consider coding it for flexibility. &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Define the abstraction to implement the algorithms&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseScraper&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;puppeteer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Puppeteer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getNumberPages&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getJobTitle&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HTML&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getJobDescription&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HTML&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getJobPaymentDetails&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HMTL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Implement the algorithms&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LinkedInScraper&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseScraper&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getNumberPages&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement algorithm&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;puppeteer&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getJobTitle&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HTML&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getJobDescription&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HTML&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement algorithm&lt;/span&gt;
    
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getJobPaymentDetails&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HMTL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GlassdoorScraper&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseScraper&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token function&quot;&gt;getNumberPages&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement algorithm&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;puppeteer&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getJobTitle&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HTML&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getJobDescription&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HTML&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement algorithm&lt;/span&gt;
    
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getJobPaymentDetails&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HMTL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Understanding Domain Entities [with Examples] - DDD w/ TypeScript]]></title><description><![CDATA[Also from the Domain-Driven Design with TypeScript series. The biggest reason why companies move towards domain-driven design is because…]]></description><link>https://khalilstemmler.com/articles/typescript-domain-driven-design/entities/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/typescript-domain-driven-design/entities/</guid><pubDate>Tue, 28 May 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;course-cta&quot;&gt;
We cover this topic in &lt;a href=&quot;https://www.essentialist.dev/master-the-essentials-of-software-design-with-typescript&quot;&gt;The Software Essentialist&lt;/a&gt; online course. Check it out if you liked this post.
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Also from the &lt;strong&gt;&lt;a href=&quot;/articles/categories/domain-driven-design/&quot;&gt;Domain-Driven Design with TypeScript&lt;/a&gt;&lt;/strong&gt; series&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The biggest reason why companies move towards domain-driven design is because their business has taken on a necessary complexity. &lt;/p&gt;
&lt;p&gt;Think about the amount of busiess logic complexity in some of the most common tools we use today like &lt;a href=&quot;https://gitlab.com&quot;&gt;GitLab&lt;/a&gt; or &lt;a href=&quot;https://netlify.com&quot;&gt;Netlify&lt;/a&gt;. They&apos;re truly &lt;a href=&quot;/articles/typescript-domain-driven-design/ddd-vs-crud-design/&quot;&gt;not dealing with modeling basic CRUD apps&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In order to manage business logic complexity, the approach is to use &lt;strong&gt;object oriented programming&lt;/strong&gt; concepts to model complex behaviour between objects; replicating what &lt;em&gt;should happen&lt;/em&gt; in a particular domain &lt;em&gt;when it&apos;s possible&lt;/em&gt; and &lt;em&gt;when it&apos;s not possible&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Domain-Driven introduces a &lt;u&gt;set of artifacts&lt;/u&gt; that we can use to model the domain.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd-intro/ddd-diagram.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s talk about another one of the &lt;strong&gt;main&lt;/strong&gt; artifacts: &lt;em&gt;entities&lt;/em&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;The-role-of-entities-in-DDD&quot; style=&quot;position:relative;&quot;&gt;The role of entities in DDD&lt;a href=&quot;#The-role-of-entities-in-DDD&quot; aria-label=&quot;The role of entities in DDD permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Entities are pretty much the bread and butter of domain modeling.&lt;/p&gt;
&lt;p&gt;These are some of the primary trait of entities.&lt;/p&gt;
&lt;h3 id=&quot;First-place-to-put-business-logic-if-it-makes-sense&quot; style=&quot;position:relative;&quot;&gt;First place to put business logic (if it makes sense)&lt;a href=&quot;#First-place-to-put-business-logic-if-it-makes-sense&quot; aria-label=&quot;First place to put business logic if it makes sense permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Entities should be the &lt;u&gt;first place that we think of to put domain logic&lt;/u&gt;. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When we want to express what a particular model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;can do&lt;/li&gt;
&lt;li&gt;when it can do it&lt;/li&gt;
&lt;li&gt;what conditions dictate when it can do that thing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We aim to place that logic &lt;strong&gt;closest to the model that it belongs to&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For example: in a job board application where employers can leave questions for applicants to answer when they apply to jobs, we can enforce some rules.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Rule #1: You can&apos;t add a question to a job that already has existing applicants.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Rule #2: You can&apos;t add more than the max amount of questions for a job.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here&apos;s a quick example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Job&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Entity&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IJobProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ... constructor&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ... private factory method&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;questions&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; QuestionsCollection &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;questions&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;hasApplicants&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;applicants&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addQuestion&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;question&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Question&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasApplicants&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Can&apos;t add a question when there are already applicants to this job.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;questions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MAX_QUESTIONS_PER_JOB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;This job already has the max amount of questions.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;questions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;question&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Sometimes, it doesn&apos;t feel natural and doesn&apos;t make sense to put certain domain logic inside of an entity.&lt;/p&gt;
&lt;p&gt;This happens when the logic we&apos;re trying figure out where to put &lt;strong&gt;doesn&apos;t involve one entity in particular&lt;/strong&gt;. There are cases where it&apos;s OK (like our &lt;code class=&quot;language-text&quot;&gt;Job&lt;/code&gt; example utilizing the &lt;code class=&quot;language-text&quot;&gt;Question&lt;/code&gt; entity),  but there are other cases where the two entities involved shouldn&apos;t necessarily know about each other (look into Aggregate Design) &lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;For example, if we were modeling a Movie Rental application, with a &lt;code class=&quot;language-text&quot;&gt;Customer&lt;/code&gt; entity and a &lt;code class=&quot;language-text&quot;&gt;Movie&lt;/code&gt; entity, where do we put the &lt;code class=&quot;language-text&quot;&gt;purchaseMovie()&lt;/code&gt; method? &lt;/p&gt;
&lt;p&gt;A &lt;code class=&quot;language-text&quot;&gt;Customer&lt;/code&gt; &lt;strong&gt;can&lt;/strong&gt; purchase a movie, but the &lt;code class=&quot;language-text&quot;&gt;Customer&lt;/code&gt; entity shouldn&apos;t need to know anything about &lt;code class=&quot;language-text&quot;&gt;Movies&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;Conversely, a &lt;code class=&quot;language-text&quot;&gt;Movie&lt;/code&gt; can be purchased by a &lt;code class=&quot;language-text&quot;&gt;Customer&lt;/code&gt;. But we wouldn&apos;t want to reference a &lt;code class=&quot;language-text&quot;&gt;Customer&lt;/code&gt; in the &lt;code class=&quot;language-text&quot;&gt;Movie&lt;/code&gt; model, because ultimately, a &lt;code class=&quot;language-text&quot;&gt;Customer&lt;/code&gt; has nothing to do with a &lt;code class=&quot;language-text&quot;&gt;Movie&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This is the type of logic that we put in a &lt;strong&gt;Domain Service&lt;/strong&gt; instead&lt;/em&gt; &lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Enforcing-model-invariants&quot; style=&quot;position:relative;&quot;&gt;Enforcing model invariants&lt;a href=&quot;#Enforcing-model-invariants&quot; aria-label=&quot;Enforcing model invariants permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In one of my previous articles, I said that &lt;a href=&quot;/articles/typescript-domain-driven-design/ddd-vs-crud-design/&quot;&gt;Domain-Driven Design is declarative&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Building an application with DDD is like creating a domain-specific language for your problem domain.&lt;/p&gt;
&lt;p&gt;In order to do that, we need to ensure that we only &lt;strong&gt;expose operations that are meaningful and valid to the domain&lt;/strong&gt;. We also ensure that &lt;a href=&quot;/wiki/invariant/&quot;&gt;class invariants&lt;/a&gt; are satisfied.&lt;/p&gt;
&lt;p&gt;Validation logic on object creation is normally delegated to &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;Value Objects&lt;/a&gt;, but what can happen (and when) is up to the entity.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;One of the earliest mistakes I was making in domain modeling was exposing getters and setters for everything.&lt;/p&gt;
&lt;p&gt;So let&apos;s be explicit about the fact that that&apos;s not the best thing to do.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Don&apos;t add getters and setters for everything.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There, I did my part.&lt;/p&gt;
&lt;p&gt;The reason why it&apos;s not good is because we need to &lt;em&gt;control how&lt;/em&gt; our objects change. We never want our objects to end up in an invalid state.&lt;/p&gt;
&lt;p&gt;Take the job board example again (particularly the part about the &lt;code class=&quot;language-text&quot;&gt;QuestionsCollection&lt;/code&gt;).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Job&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Entity&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IJobProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ... constructor&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ... private factory method&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;questions&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; QuestionsCollection &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;questions&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addQuestion&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;question&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Question&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;questions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MAX_QUESTIONS_PER_JOB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;This job already has the max amount of questions.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;questions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;question&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Do you notice how the &lt;code class=&quot;language-text&quot;&gt;questions&lt;/code&gt; array &lt;em&gt;doesn&apos;t&lt;/em&gt; have a setter defined for it?&lt;/p&gt;
&lt;p&gt;Our domain logic specifies that someone &lt;em&gt;shouldn&apos;t&lt;/em&gt; be able to add more than the max amount of questions per job. &lt;/p&gt;
&lt;p&gt;If we had a public setter for &lt;code class=&quot;language-text&quot;&gt;questions&lt;/code&gt;, there&apos;s nothing stopping someone from &lt;u&gt;completely circumventing the domain logic&lt;/u&gt; by doing:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;job&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;questions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// question objects&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is &lt;strong&gt;encapsulation&lt;/strong&gt;: one of the 4 principles of Object-oriented programming. Encapsulation is an act of data integrity; and that&apos;s especially important in domain-modeling.&lt;/p&gt;
&lt;h3 id=&quot;Identity-and-lookup&quot; style=&quot;position:relative;&quot;&gt;Identity and lookup&lt;a href=&quot;#Identity-and-lookup&quot; aria-label=&quot;Identity and lookup permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;An entity is different from a Value Object primarily due to the fact that an Entity has an identity while a Value Object does not.&lt;/p&gt;
&lt;p&gt;Entities: think &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Job&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Organization&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Message&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Conversation&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Value Objects: think &lt;code class=&quot;language-text&quot;&gt;Name&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;MessageText&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;JobTitle&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;ConversationName&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Typically, a single Entity will be a model that references other Value Objects and Entities.&lt;/p&gt;
&lt;p&gt;Here&apos;s what a basic &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; entity might look like.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IUserProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Username&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  active&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Entity&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IUserProps&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Username &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Email &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isActive&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;active&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userPropsResult&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;againstNullOrUndefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; propName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; propName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;email&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; propName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;active&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;active &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userPropsResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userPropsResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;During the lifecycle of an entity, it may need to be &lt;code class=&quot;language-text&quot;&gt;Stored&lt;/code&gt; to a database, &lt;code class=&quot;language-text&quot;&gt;Reconstituted&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Modified&lt;/code&gt; before being deleted or archived.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I use UUIDs instead of Auto-incremented IDs for entity creation. See &lt;a href=&quot;/articles/auto-increment-or-uuid/&quot;&gt;this article&lt;/a&gt; for why.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;Entity-lifecycle&quot; style=&quot;position:relative;&quot;&gt;Entity lifecycle&lt;a href=&quot;#Entity-lifecycle&quot; aria-label=&quot;Entity lifecycle permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is what the lifecycle of an entity looks like, generally.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd/entity-lifecycle.svg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Creation&quot; style=&quot;position:relative;&quot;&gt;Creation&lt;a href=&quot;#Creation&quot; aria-label=&quot;Creation permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To create entities, just like Value Objects, we use &lt;strong&gt;Factories&lt;/strong&gt; of some sort. &lt;/p&gt;
&lt;p&gt;Most of the examples on this site use basic &lt;strong&gt;Factory methods&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;What&apos;s a &lt;em&gt;factory method&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;Remember this bit in the previous example?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserProps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userPropsResult&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Guard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;againstNullOrUndefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; propName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; propName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;email&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; propName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;active&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;active &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userPropsResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;props&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userPropsResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;createUser&lt;/code&gt; method is a &lt;strong&gt;Factory Method&lt;/strong&gt; that handles creation of the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; entity.&lt;/p&gt;
&lt;p&gt;Notice that we can&apos;t use the &lt;code class=&quot;language-text&quot;&gt;new&lt;/code&gt; keyword and do:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &amp;lt;= constructor is private&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Again, &lt;strong&gt;encapsulation&lt;/strong&gt; and &lt;strong&gt;data integrity&lt;/strong&gt;. We want to control how instances of &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt; get into the execution of our domain layer code.&lt;/p&gt;
&lt;p&gt;If we had hundreds of different types of &lt;code class=&quot;language-text&quot;&gt;Users&lt;/code&gt; that we wanted to be able to create, we could either write more factory methods, or we could try using &lt;a href=&quot;/wiki/abstract-factory/&quot;&gt;Abstract Factories&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;Entity-base-class&quot; style=&quot;position:relative;&quot;&gt;Entity base class&lt;a href=&quot;#Entity-base-class&quot; aria-label=&quot;Entity base class permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Note that you should never fully copy someone else&apos;s Entity or Value Object class. For something this important to your domain (this is essentially the family jewels), it would be worthwhile for you roll your own. You might have different needs, but feel free to start here and change as necessary&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UniqueEntityID &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./types&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isEntity &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; v &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; Entity&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; v &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Entity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Entity&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;readonly&lt;/span&gt; _id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Take note of this particular nuance here:&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Why is &quot;id&quot; optional?&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; id &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; id &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Entities are compared based on their referential&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// equality.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;equals&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;object&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Entity&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;object &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; object &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; object&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isEntity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;object&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here&apos;s what&apos;s important to note about the &lt;code class=&quot;language-text&quot;&gt;Entity&amp;lt;T&amp;gt;&lt;/code&gt; base class:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Entity&amp;lt;T&amp;gt;&lt;/code&gt; is an abstract class. This means that we can&apos;t instantiate it directly. We can, however, &lt;em&gt;subclass&lt;/em&gt; it. That&apos;s a logical design decision. An entity only makes sense to exist if it has a particular type to it like &lt;code class=&quot;language-text&quot;&gt;Car extends Entity&amp;lt;ICarProps&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt; for this class is &lt;code class=&quot;language-text&quot;&gt;readonly&lt;/code&gt;. So it shouldn&apos;t be able to be changed once instantiated. Also a pretty logical design decision if you ask me.&lt;/li&gt;
&lt;li&gt;We&apos;re using the &lt;code class=&quot;language-text&quot;&gt;equals(object?: Entity&amp;lt;T&amp;gt;)&lt;/code&gt; method to determine if an entity is &lt;em&gt;referentially&lt;/em&gt; equivalent to another entity. If referential equality doesn&apos;t determine that they&apos;re the same, we compare the &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt; of this entity vs. the one we&apos;recomparing it to.&lt;/li&gt;
&lt;li&gt;The props for the class are stored in &lt;code class=&quot;language-text&quot;&gt;this.props&lt;/code&gt;. The reason for that is because we want to &lt;strong&gt;leave the decision to the subclass on which properties getters and setters should be defined&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;Optional-id-field&quot; style=&quot;position:relative;&quot;&gt;Optional id field&lt;a href=&quot;#Optional-id-field&quot; aria-label=&quot;Optional id field permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The most interesting design decision to note here is that the &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt; field is &lt;strong&gt;optional&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Why would we do that?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Well, when the &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt; is known (because we&apos;ve already created it), we can pass it in. &lt;/p&gt;
&lt;p&gt;When we don&apos;t know the &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt; (because we haven&apos;t created it yet), we create a new one (&lt;a href=&quot;/articles/auto-increment-or-uuid/&quot;&gt;32-bit UUID&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;This allows us to address both the &lt;strong&gt;Creation&lt;/strong&gt; and &lt;strong&gt;Reconstitution&lt;/strong&gt; events in the entity lifecycle.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/ddd/entity-creation.svg&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;Storage&quot; style=&quot;position:relative;&quot;&gt;Storage&lt;a href=&quot;#Storage&quot; aria-label=&quot;Storage permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;After we&apos;ve created an entity in memory, we&apos;ll want a way to store it to the database.&lt;/p&gt;
&lt;p&gt;This is done with the help of a &lt;strong&gt;Repository&lt;/strong&gt; and a &lt;strong&gt;Mapper&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Repository&lt;/strong&gt; is an artifact used to persist and retrieve domain objects from whatever type of persistence technology you&apos;d like (relational database, noSQL database, JSON file, text files).&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Mapper&lt;/strong&gt; is a file that simply maps a domain object to the format needed to save it in a database, and vice versa (into a Domain object).&lt;/p&gt;
&lt;p&gt;Here&apos;s the skeleton of a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; repo utilizing the Sequelize ORM.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IUserRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;searchUsersByEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UsersCollection&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getUsers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;config&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserSearchConfig&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UsersCollection&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getUsersByRole&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;config&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserSearchConfig&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; role&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Role&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UsersCollection&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SequelizeUserRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IUserRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; sequelizeModels&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;sequelizeModels&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sequelizeModels &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; sequelizeModels&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;exists&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement specific algorithm using sequelize orm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;searchUsersByEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UsersCollection&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement specific algorithm using sequelize orm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getUsers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;config&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserSearchConfig&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UsersCollection&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement specific algorithm using sequelize orm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getUsersByRole&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    config&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserSearchConfig&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    role&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Role
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UsersCollection&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement specific algorithm using sequelize orm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement specific algorithm using sequelize orm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement specific algorithm using sequelize orm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let&apos;s say that we wanted to implement the &lt;code class=&quot;language-text&quot;&gt;getUsers&lt;/code&gt; method. &lt;/p&gt;
&lt;p&gt;We&apos;d want to retrieve all the users using the Sequelize-specific syntax, and then map those &lt;a href=&quot;/wiki/active-record/&quot;&gt;Active Records&lt;/a&gt; into &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; domain objects.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; UserMap &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../mappers&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SequelizeUserRepo&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IUserRepo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; sequelizeModels&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;getUsers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;config&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserSearchConfig&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UsersCollection&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; UserModel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sequelizeModels&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;BaseUser&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; queryObject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createQueryObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;config&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; users&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; UserModel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queryObject&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; UserMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;u&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here&apos;s what the mapper might look like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserMap&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Mapper&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toDTO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserDTO &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    userName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    userEmail&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toPersistence&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      user_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      user_name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      user_email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      is_active&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isActive&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toDomain&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; nameOrResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; UserName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user_name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emailOrResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; UserEmail&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user_email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; passwordOrResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; UserPassword&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user_password&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; nameOrResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      password&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; passwordOrResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; emailOrResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      active&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;is_active&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UniqueEntityID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user_id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See how narrowly scoped this class is? It&apos;s a great example of the &lt;a href=&quot;/articles/solid-principles/solid-typescript/&quot;&gt;Single Responsibility Principle&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;Reconstitution&quot; style=&quot;position:relative;&quot;&gt;Reconstitution&lt;a href=&quot;#Reconstitution&quot; aria-label=&quot;Reconstitution permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;After we&apos;ve created an entity and persisted it into the database, at some point, we&apos;ll want to pull it out and use it for operations.&lt;/p&gt;
&lt;p&gt;Again, this is a job easily maintained by the &lt;strong&gt;repository&lt;/strong&gt; and &lt;strong&gt;mapper&lt;/strong&gt; classes.&lt;/p&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There&apos;s more to domain objects like &lt;strong&gt;Aggregate Roots&lt;/strong&gt; and &lt;strong&gt;Domain Events&lt;/strong&gt; but you can get started modeling a lot of your domain with just &lt;strong&gt;Entities&lt;/strong&gt; and &lt;strong&gt;Value Objects&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In the next few articles, we&apos;ll talk about how to use &lt;strong&gt;Domain Events&lt;/strong&gt; in a real world Sequelize + Node + TypeScript app and how to model &lt;strong&gt;Aggregates&lt;/strong&gt;.&lt;/p&gt;
&lt;p class=&quot;course-cta&quot;&gt;
We cover this topic in &lt;a href=&quot;https://www.essentialist.dev/master-the-essentials-of-software-design-with-typescript&quot;&gt;The Software Essentialist&lt;/a&gt; online course. Check it out if you liked this post.
&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;This branches into Aggregate Design. Certain entities do belong in scope of others. We call the entities at the top of this &lt;em&gt;tree&lt;/em&gt;, an Aggregate Root.&lt;/p&gt;
&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;This is where we locate domain logic that doesn&apos;t belong to any one object conceptually. Not to be confused with an Application Service. Domain Services only operate on Domain Objects, whereas Application Services are artifacts that are unpure to the domain, that may pull data from external resources (APIs, object databases, etc, and so on).&lt;/p&gt;
&lt;a href=&quot;#fnref-2&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[No title]]></title><description><![CDATA[You know Sequelize, TypeORM, and Mongoose?  Those are all ORMs. When you return an instance of a row (or document), being able to make…]]></description><link>https://khalilstemmler.com/wiki/active-record/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/active-record/</guid><pubDate>Sat, 25 May 2019 04:05:26 GMT</pubDate><content:encoded>&lt;p&gt;You know &lt;a href=&quot;http://docs.sequelizejs.com/&quot;&gt;Sequelize&lt;/a&gt;, &lt;a href=&quot;https://github.com/typeorm/typeorm&quot;&gt;TypeORM&lt;/a&gt;, and &lt;a href=&quot;https://mongoosejs.com/&quot;&gt;Mongoose&lt;/a&gt;? &lt;/p&gt;
&lt;p&gt;Those are all ORMs. When you return an instance of a row (or document), being able to make changes to the database row (that the instance references) is a popular usage of the Active Record pattern.&lt;/p&gt;
&lt;p&gt;The Active Record pattern was initially documented by &lt;a href=&quot;https://en.wikipedia.org/wiki/Active_record_pattern&quot;&gt;Martin Fowler&lt;/a&gt; &lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Updating the &apos;name&apos; column of a user using Sequelize.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; user_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Don Draper&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using instances of row objects returned from the ORM technology of our choice, we can Create, Read, Update and Delete instances of pretty much anything inside of the database.&lt;/p&gt;
&lt;p&gt;Pretty cool!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[No title]]></title><description><![CDATA[See this article. 🙂]]></description><link>https://khalilstemmler.com/wiki/clean-architecture/</link><guid isPermaLink="false">https://khalilstemmler.com/wiki/clean-architecture/</guid><pubDate>Sat, 25 May 2019 04:05:26 GMT</pubDate><content:encoded>&lt;p&gt;See &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/&quot;&gt;this article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;🙂&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Knowing When CRUD & MVC Isn't Enough | Enterprise Node.js + TypeScript]]></title><description><![CDATA[If you're a developer, you've most definitely heard about MVC.  It's the most popular and well-understood architecture for creating…]]></description><link>https://khalilstemmler.com/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/enterprise-typescript-nodejs/when-crud-mvc-isnt-enough/</guid><pubDate>Fri, 24 May 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;If you&apos;re a developer, you&apos;ve &lt;strong&gt;most definitely&lt;/strong&gt; heard about MVC. &lt;/p&gt;
&lt;p&gt;It&apos;s &lt;em&gt;the most popular and well-understood architecture&lt;/em&gt; for creating applications that involve user interfaces. &lt;/p&gt;
&lt;p&gt;For a lot of developers, myself included, MVC is the &lt;em&gt;first&lt;/em&gt; type of architecture we learn about, and it&apos;s our introduction to full-stack web development.&lt;/p&gt;
&lt;p&gt;As &lt;del&gt;a founder&lt;/del&gt; ex co-founder @ &lt;strong&gt;Univjobs&lt;/strong&gt;, &lt;del&gt;an early-stage startup&lt;/del&gt; a very, very dead startup, I&apos;ve realized that MVC is &lt;strong&gt;amazing&lt;/strong&gt; because it will enable you get things done &lt;em&gt;fast&lt;/em&gt; as hell.&lt;/p&gt;
&lt;p&gt;And getting things done fast in order to validate them quickly is one of the most important things about engineering in a startup.&lt;/p&gt;
&lt;p&gt;But I&apos;ve also discovered that MVC (the way it&apos;s been popularized, at least) &lt;u&gt;is not going to cut it&lt;/u&gt; for enterprise applications.&lt;/p&gt;
&lt;p&gt;The biggest challenge in complex apps is that the &lt;code class=&quot;language-text&quot;&gt;M&lt;/code&gt; in MVC doesn&apos;t describe how to organize your business logic.&lt;/p&gt;
&lt;p&gt;In this article, I&apos;ll cover:&lt;/p&gt;
&lt;ul class=&quot;aside&quot;&gt;
  &lt;li&gt;How to reason about using ORMs directly in CRUD apps&lt;/li&gt;
  &lt;li&gt;How to identify when CRUD apps have become too complex&lt;/li&gt;
  &lt;li&gt;How domain modeling can bring structure to the &apos;M&apos; part of MVC&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;MVC-Basics&quot; style=&quot;position:relative;&quot;&gt;MVC Basics&lt;a href=&quot;#MVC-Basics&quot; aria-label=&quot;MVC Basics permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;view&lt;/code&gt; in MVC is the visual representation of our app. It might show us charts, diagrams, forms, etc. This is our window into the application as end users.&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;controller&lt;/code&gt; is an artifact &lt;em&gt;should&lt;/em&gt;:  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;wait for HTTP requests&lt;/li&gt;
&lt;li&gt;delegate business logic to models and services and saves the result of that transaction to persistence (sometimes we don&apos;t do this)&lt;/li&gt;
&lt;li&gt;return a meaningful response&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lastly, the &lt;code class=&quot;language-text&quot;&gt;model&lt;/code&gt; is meant to handle all of the &lt;code class=&quot;language-text&quot;&gt;rules&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;logic&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;data&lt;/code&gt;.  &lt;/p&gt;
&lt;h2 id=&quot;Models-in-popular-ORMs&quot; style=&quot;position:relative;&quot;&gt;Models in popular ORMs&lt;a href=&quot;#Models-in-popular-ORMs&quot; aria-label=&quot;Models in popular ORMs permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The model has the &lt;em&gt;most unclear role&lt;/em&gt; out of all of the parts of MVC.&lt;/p&gt;
&lt;p&gt;I think a large part of the confusion is that when people think of a &lt;code class=&quot;language-text&quot;&gt;Model&lt;/code&gt;, they think of an ORM (object-relational mapping) tool.&lt;/p&gt;
&lt;p&gt;It’s a common practice in Node.js backend applications to use an ORM in order to interact with the database. &lt;/p&gt;
&lt;h3 id=&quot;Models-in-MongoDB-with-Mongoose&quot; style=&quot;position:relative;&quot;&gt;Models in MongoDB with Mongoose&lt;a href=&quot;#Models-in-MongoDB-with-Mongoose&quot; aria-label=&quot;Models in MongoDB with Mongoose permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; mongoose &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;mongoose&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; validator &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;validator&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; emailSchema &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;mongoose&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Schema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    required&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    unique&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    lowercase&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;validate&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; validator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; mongoose&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Email&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; emailSchema&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Models-in-Sequelize&quot; style=&quot;position:relative;&quot;&gt;Models in Sequelize&lt;a href=&quot;#Models-in-Sequelize&quot; aria-label=&quot;Models in Sequelize permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;sequelize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; sequelize&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;define&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;user&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;INTEGER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          primaryKey&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          autoIncrement&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;STRING&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;Models-in-TypeORM&quot; style=&quot;position:relative;&quot;&gt;Models in TypeORM&lt;a href=&quot;#Models-in-TypeORM&quot; aria-label=&quot;Models in TypeORM permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;Entity&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PrimaryGeneratedColumn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Column&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;typeorm&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

@&lt;span class=&quot;token function&quot;&gt;Entity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    @&lt;span class=&quot;token function&quot;&gt;PrimaryGeneratedColumn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    @&lt;span class=&quot;token function&quot;&gt;Column&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    @&lt;span class=&quot;token function&quot;&gt;Column&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    @&lt;span class=&quot;token function&quot;&gt;Column&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    age&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In each of these examples, the &lt;code class=&quot;language-text&quot;&gt;Model&lt;/code&gt; is a single file which defines the table or object schema.&lt;/p&gt;
&lt;p&gt;The next question that people start to ask is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Where does my business logic go?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It&apos;s supposed to be a part of the model, right? Since we only have 3 components to MVC, and we&apos;re sure it&apos;s not in the &lt;code class=&quot;language-text&quot;&gt;controller&lt;/code&gt; and we&apos;re &lt;em&gt;absolutely&lt;/em&gt; sure it&apos;s not in &lt;code class=&quot;language-text&quot;&gt;view&lt;/code&gt;, it&apos;s the &lt;code class=&quot;language-text&quot;&gt;model&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But how? Our ORM models are so &lt;em&gt;slim&lt;/em&gt;. They&apos;re just definition files.&lt;/p&gt;
&lt;p&gt;And even moreso, each of these ORM models are &lt;a href=&quot;/wiki/clean-architecture/&quot;&gt;infrastructure concerns&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Putting business logic directly in the ORM objects (which are neat implementations of the &lt;a href=&quot;/wiki/active-record/&quot;&gt;Active Record Pattern&lt;/a&gt;) is a violation of the Separation of Concerns principle in a &lt;a href=&quot;/wiki/clean-architecture/&quot;&gt;Clean Architecture&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So then where does the business logic go?&lt;/p&gt;
&lt;p&gt;Because we don&apos;t want to put logic directly in our ORM &lt;code class=&quot;language-text&quot;&gt;model&lt;/code&gt;, we take &lt;em&gt;shortcuts&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Sometimes, we &lt;u&gt;end up putting everything in the controller&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;Sometimes, we &lt;u&gt;end up creating services and putting it in that&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;And quite honestly, doing that isn&apos;t always a bad thing. It all depends on the context.&lt;/p&gt;
&lt;p&gt;In my opinion, whether or not that&apos;s a bad thing can be determined by the answer to this question.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Are you building a CRUD app or are you building a complex app?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;CRUD-apps&quot; style=&quot;position:relative;&quot;&gt;CRUD apps&lt;a href=&quot;#CRUD-apps&quot; aria-label=&quot;CRUD apps permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You might recall that CRUD stands for &lt;code class=&quot;language-text&quot;&gt;Create&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Read&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Update&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Delete&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In CRUD applications, there&apos;s not a whole lot of &lt;strong&gt;business logic&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;With CRUD apps, we&apos;ll often design them &lt;a href=&quot;/articles/typescript-domain-driven-design/ddd-vs-crud-design/&quot;&gt;REST-first&lt;/a&gt; because they fit so perfectly into RESTful APIs.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;RESTful API&lt;/strong&gt; call can be reasoned to be: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt; the combination of a route (ie: which model(s) to interact with), and a method (how to interact with the specified model(s))&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;GET&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;users  &lt;span class=&quot;token comment&quot;&gt;// GET the user model (collection)&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;DELETE&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;userId &lt;span class=&quot;token comment&quot;&gt;// DELETE a particular user&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;POST&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// CREATE a new user&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In &lt;a href=&quot;/articles/typescript-domain-driven-design/ddd-vs-crud-design/&quot;&gt;REST-first&lt;/a&gt; apps, there&apos;s very little actual &lt;strong&gt;business logic&lt;/strong&gt; that needs to take place, and using our ORMs directly from the controller or service will allow us perform operations on our &lt;code class=&quot;language-text&quot;&gt;models&lt;/code&gt; quickly. &lt;/p&gt;
&lt;h2 id=&quot;The-role-of-ORMs-in-simple-CRUD-apps&quot; style=&quot;position:relative;&quot;&gt;The role of ORMs in simple CRUD apps&lt;a href=&quot;#The-role-of-ORMs-in-simple-CRUD-apps&quot; aria-label=&quot;The role of ORMs in simple CRUD apps permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Take this example.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; User &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;201&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Look at how simple that is to understand. &lt;/p&gt;
&lt;p&gt;And it probably took us no time to do.&lt;/p&gt;
&lt;p&gt;Although, we &lt;em&gt;are&lt;/em&gt; now relying on the database to perform validation logic (yep, that&apos;s a form of business logic). However, we might be willing to sacrifice that in order to get something up and running quickly (for the better approach, see how &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;Value Objects in DDD&lt;/a&gt; addresses this).&lt;/p&gt;
&lt;p&gt;But just notice that as soon as we were to add &lt;em&gt;any sort&lt;/em&gt; of additional validation logic to this controller, we would be writing code somewhere that it &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;probably doesn&apos;t belong&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This leads us to doing quick fixes such as creating several &lt;em&gt;helper files and folders&lt;/em&gt; and &lt;u&gt;moving validation logic to services&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;That&apos;s one way to build an &lt;a href=&quot;/wiki/anemic-domain-model/&quot;&gt;Anemic Domain Model&lt;/a&gt; and scatter plenty of domain logic throughout an app without knowing it. &lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Ultimately, it&apos;s not a bad idea to build anemic domain models and refer to our ORMs directly from the services and controllers when we&apos;re working on simple CRUD apps.&lt;/p&gt;
&lt;p&gt;You can go hella fast.&lt;/p&gt;
&lt;p&gt;&lt;u&gt;This is what early-stage startup code&lt;/u&gt; is &lt;em&gt;made of&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;But things start to get a little bit out of hand when apps grow in complexity.&lt;/p&gt;
&lt;h2 id=&quot;Story-time-What-when-happens-CRUD-apps-turn-complex&quot; style=&quot;position:relative;&quot;&gt;Story time: What when happens CRUD apps turn complex&lt;a href=&quot;#Story-time-What-when-happens-CRUD-apps-turn-complex&quot; aria-label=&quot;Story time What when happens CRUD apps turn complex permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Univjobs is a niche job board for students and recent-grads. &lt;/p&gt;
&lt;p&gt;When new jobs get posted by employers, we have to verify them before they go live in the app so that students don&apos;t get taken advantage of by employers who want to pay them less than minimum wage.&lt;/p&gt;
&lt;p&gt;This means we needed a way to &lt;code class=&quot;language-text&quot;&gt;approve&lt;/code&gt; a job posting.&lt;/p&gt;
&lt;p&gt;The moment I realized things were about to get a lot less CRUD-y was when I defined a method in a service class called &lt;code class=&quot;language-text&quot;&gt;postJobCreatedHooks(jobId: string)&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;postJobCreatedHooks&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;jobId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Charge the customer.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Add the job to our queue of new jobs for the week.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Trigger a gatsby build to rebuild our Gatsbyjs site.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Post the job to social.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Do a bunch of other stuff.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Send an email to the customer letting them know their job is active.&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;WHOA THERE.&lt;/p&gt;
&lt;p&gt;We did all of that in a single method &lt;code class=&quot;language-text&quot;&gt;JobService&lt;/code&gt; method. Of course it was broken up and other services were injected, but that&apos;s a lot for a &lt;code class=&quot;language-text&quot;&gt;JobService&lt;/code&gt; to have to know about. That also seems like a blatant violation of the &lt;a href=&quot;/articles/solid-principles/solid-typescript/#SRP&quot;&gt;Single Responsibility Principle&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I wanted to do something after the &lt;code class=&quot;language-text&quot;&gt;Job&lt;/code&gt; model changed in a particular way (from verified = &lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The thing is, a lot of these ORMs actually have mechanisms built in to execute code after things get saved to the database.&lt;/p&gt;
&lt;p&gt;For example, the &lt;a href=&quot;http://docs.sequelizejs.com/manual/hooks.html&quot;&gt;Sequelize docs&lt;/a&gt; has hooks for each of these lifecycle events.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;(1)
  beforeBulkCreate(instances, options)
  beforeBulkDestroy(options)
  beforeBulkUpdate(options)
(2)
  beforeValidate(instance, options)
(-)
  validate
(3)
  afterValidate(instance, options)
  - or -
  validationFailed(instance, options, error)
(4)
  beforeCreate(instance, options)
  beforeDestroy(instance, options)
  beforeUpdate(instance, options)
  beforeSave(instance, options)
  beforeUpsert(values, options)
(-)
  create
  destroy
  update
(5)
  afterCreate(instance, options)
  afterDestroy(instance, options)
  afterUpdate(instance, options)
  afterSave(instance, options)
  afterUpsert(created, options)
(6)
  afterBulkCreate(instances, options)
  afterBulkDestroy(options)
  afterBulkUpdate(options)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In order to hook one of these up, you&apos;d hook it up to your ORM model definition file.&lt;/p&gt;
&lt;p&gt;Like this for example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Job&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
Job&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; DataTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;STRING&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; DataTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;ENUM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    values&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;initial&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;verified&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;rejected&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  hooks&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;afterSave&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;job&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// do all our domain logic here?&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  sequelize
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But there we go again... We&apos;re back to violating the Separation of Concerns at the &lt;a href=&quot;/wiki/clean-architecture/&quot;&gt;architectural level&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We don&apos;t want to put Domain layer business logic in an infrastructure concern.&lt;/p&gt;
&lt;p&gt;And even if we were OK with doing that, surely, it wouldn&apos;t be a good idea to pollute our &lt;code class=&quot;language-text&quot;&gt;Model&lt;/code&gt; with service calls in order to do all this stuff.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;hooks&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;afterSave&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;job&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;job&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;verified&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;verified&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Charge the customer.&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Add the job to our queue of new jobs for the week.&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Trigger a gatsby build to rebuild our Gatsbyjs site.&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Post the job to social.&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Update the visibility of the job so that only the targeted audience that is allowed to see the job could see the job.&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// Send an email to the customer letting them know their job is active.&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Also, injecting all the dependencies in there would be a coupled mess.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Back to the story,&lt;/p&gt;
&lt;p&gt;To make matters worse, we just kept identifying more and more things that needed to happen after we verified a job.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;postJobCreatedHooks&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;jobId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Charge the customer.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Add the job to our queue of new jobs for the week.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Trigger a gatsby build to rebuild our Gatsbyjs site.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Post the job to social.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Do a bunch of other stuff.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Send an email to the customer letting them know their job is active.&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// and more... &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// and more......&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the architecture world, we call this way of coding a big ol’ &lt;strong&gt;Transaction Script&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Transaction-Scripts&quot; style=&quot;position:relative;&quot;&gt;Transaction Scripts&lt;a href=&quot;#Transaction-Scripts&quot; aria-label=&quot;Transaction Scripts permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Generally speaking, there are two main ways to organize your backend code.&lt;/p&gt;
&lt;p&gt;Using a &lt;strong&gt;Transaction Script&lt;/strong&gt; or a &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Model&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A transaction script is a pattern documented by &lt;a href=&quot;https://martinfowler.com/eaaCatalog/transactionScript.html&quot;&gt;Martin Fowler&lt;/a&gt;. It&apos;s a &lt;em&gt;procedural&lt;/em&gt;  approach to handling business logic. It&apos;s also the simplest form of expressing domain logic that works really well in simple apps.&lt;/p&gt;
&lt;p&gt;Transaction Scripts are an excellent choice for CRUD apps with little business logic.&lt;/p&gt;
&lt;p&gt;The reason why a lot of CRUD apps that become more and more complex fail is because they fail to switch from the transaction script approach to a Domain Model. &lt;/p&gt;
&lt;h2 id=&quot;Switching-to-a-Domain-Model&quot; style=&quot;position:relative;&quot;&gt;Switching to a Domain Model&lt;a href=&quot;#Switching-to-a-Domain-Model&quot; aria-label=&quot;Switching to a Domain Model permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are plenty of excellent topics in &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design&lt;/a&gt; to address, but one of best things about DDD is the concept of “Domain Events”.&lt;/p&gt;
&lt;h3 id=&quot;Domain-Events&quot; style=&quot;position:relative;&quot;&gt;Domain Events&lt;a href=&quot;#Domain-Events&quot; aria-label=&quot;Domain Events permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Domain Events signify that something significant to your domain has just occurred.&lt;/p&gt;
&lt;p&gt;Doing a workshop-based activity called &lt;a href=&quot;https://en.wikipedia.org/wiki/Event_storming&quot;&gt;Event Storming&lt;/a&gt;, you can quickly identify all the relevant Domain Events that exist in your problem domain.&lt;/p&gt;
&lt;p&gt;Sometimes, when one event occurs, it might signify that other events need to occur in reaction to it. That’s not always the case. But when it is, it allows for some really elegant and expressive ways to structure business logic.&lt;/p&gt;
&lt;p&gt;This is what happens to our architecture when we post a job using &lt;strong&gt;Domain Events&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/enterprise-node/mvc/mvc.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;If we&apos;re using &lt;strong&gt;Package by Module*&lt;/strong&gt;, the Jobs module (also referred to as a subdomain) can dispatch a &lt;code class=&quot;language-text&quot;&gt;JobVerified&lt;/code&gt; domain event.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JobVerified&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IDomainEvent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; job&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Job&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;job&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Job&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;      
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;job &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; job&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, other &lt;strong&gt;modules (or subdomains)*&lt;/strong&gt; that are interested in that event can subscribe to it, and carry out their own business logic from their respective module.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/enterprise-node/mvc/mvc-2.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;OK, so I know we just used a few new terms there. &lt;/p&gt;
&lt;p&gt;What&apos;s a subdomain? And what does Package by Module mean?&lt;/p&gt;
&lt;h3 id=&quot;Subdomains-and-Packaging-by-Module&quot; style=&quot;position:relative;&quot;&gt;Subdomains and Packaging by Module&lt;a href=&quot;#Subdomains-and-Packaging-by-Module&quot; aria-label=&quot;Subdomains and Packaging by Module permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In Domain-Driven Design, a &lt;strong&gt;subdomain&lt;/strong&gt; is way to decompose your problem domain into sub-domains. These usually reflects some organizational structure (billing, users, notifications, hr, etc). &lt;/p&gt;
&lt;p&gt;And &lt;strong&gt;packaging by module&lt;/strong&gt; refers to how we choose to arrange our code in folders. In this case, we arrange our code by subdomains, which is more readable than &lt;strong&gt;packaging by infrastructure&lt;/strong&gt; where that top level of folders is organized by the type of technical artifacts it contains (/controllers, /routes, /views, etc.. blehh).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/enterprise-node/mvc/folder-structure.png&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;caption&quot;&gt;A &quot;Package by Module&quot; folder structure. Each module is a separate subdomain.&lt;/div&gt;
&lt;p&gt;Because the entire application is deployed in a single &lt;strong&gt;Bounded Context&lt;/strong&gt;, this makes for communication between subdomains using Domain Events really nice and easy, as I can hook up messaging between them over the same process.&lt;/p&gt;
&lt;p&gt;In DDD, we call a deployment of any number of subdomains, a &lt;strong&gt;bounded context&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&quot;Single-Bounded-Context&quot; style=&quot;position:relative;&quot;&gt;Single Bounded Context&lt;a href=&quot;#Single-Bounded-Context&quot; aria-label=&quot;Single Bounded Context permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;So in my example, because my monolith is running in a single process, that&apos;s a &lt;u&gt;single bounded context&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/enterprise-node/mvc/bounded-context.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;And as long as we’ve packaged our application by module/component, we can eventually split them up into microservices. That means a single bounded context per subdomain. A 1-to-1.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/enterprise-node/mvc/microservices.svg&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;caption&quot;&gt;Multiple bounded contexts / microservices&lt;/div&gt;
&lt;p&gt;That’s what we could do if we needed to scale out. We could have separate teams manage separate parts of the enterprise and integrate with each other. &lt;/p&gt;
&lt;p&gt;But, I’m not ready to take on that challenge of managing all of those separate deployments today. I’m sticking with the monolith architecture for a while longer.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you don&apos;t understand this whole bounded-contexts and subdomains thing yet, don&apos;t worry. It requires a &lt;strong&gt;lot&lt;/strong&gt; more explaination to fully grasp. It took me a little while to get. I&apos;ll write about them some more in the &lt;a href=&quot;/articles/categories/domain-driven-design/&quot;&gt;Domain-Driven Design Series&lt;/a&gt;. I&apos;ll also cover how to create Domain Events and how to subscribe to &apos;em.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In conclusion,&lt;/p&gt;
&lt;p&gt;Here&apos;s what I think the main takeaways should be from this article:&lt;/p&gt;
&lt;h4 id=&quot;Know-when-we-need-a-domain-model&quot; style=&quot;position:relative;&quot;&gt;Know when we need a domain model&lt;a href=&quot;#Know-when-we-need-a-domain-model&quot; aria-label=&quot;Know when we need a domain model permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;When we realize that we&apos;re getting a lot of business logic and rules that don&apos;t quite fit within the CRUD confines, it might be a sign to move from a transaction script to domain modeling.&lt;/p&gt;
&lt;h4 id=&quot;Frameworks-arent-a-silver-bullet&quot; style=&quot;position:relative;&quot;&gt;Frameworks aren&apos;t a silver bullet&lt;a href=&quot;#Frameworks-arent-a-silver-bullet&quot; aria-label=&quot;Frameworks arent a silver bullet permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Frameworks, like &lt;a href=&quot;https://docs.nestjs.com/&quot;&gt;Nest.js&lt;/a&gt; help us become productive a lot faster, and they help by making architectural decisions for us, but we still need to learn how to do domain modeling (or something else fancy) if our CRUD app becomes sufficiently complex.&lt;/p&gt;
&lt;p&gt;Frameworks can&apos;t always make that decision for us.&lt;/p&gt;
&lt;h4 id=&quot;DDD-is-an-introduction-to-some-really-interesting-architectures&quot; style=&quot;position:relative;&quot;&gt;DDD is an introduction to some really interesting architectures&lt;a href=&quot;#DDD-is-an-introduction-to-some-really-interesting-architectures&quot; aria-label=&quot;DDD is an introduction to some really interesting architectures permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;DDD is a gateway to some really interesting event-driven architectures like CQRS (command query response segregation) and Event Sourcing.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[SOLID Principles: The Software Developer's Framework to Robust & Maintainable Code [with Examples]]]></title><description><![CDATA[Writing code can be like pouring concrete. If what you've written in the past doesn't suit your needs today, it can be expensive to change…]]></description><link>https://khalilstemmler.com/articles/solid-principles/solid-typescript/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/solid-principles/solid-typescript/</guid><pubDate>Sat, 18 May 2019 15:04:10 GMT</pubDate><content:encoded>&lt;div class=&quot;solid-book-cta course-cta&quot;&gt;
  &lt;div class=&quot;solid-book-logo-container&quot;&gt;
    &lt;img src=&quot;/img/resources/solid-book/book-logo.png&quot;/&gt;
  &lt;/div&gt;
  &lt;p&gt;This article is part of Solid Book - The Software Design &amp; Architecture Handbook w/ TypeScript + Node.js. &lt;a href=&quot;https://solidbook.io&quot;&gt;Check it out&lt;/a&gt; if you like this post.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Writing code can be like pouring concrete.&lt;/p&gt;
&lt;p&gt;If what you&apos;ve written in the past doesn&apos;t suit your needs today, it can be expensive to change.&lt;/p&gt;
&lt;p&gt;And change is inevitable. &lt;/p&gt;
&lt;p&gt;So if we&apos;re writing code, we need to write code that can be changed.&lt;/p&gt;
&lt;p&gt;That&apos;s a lot harder than it sounds.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;My initial approach to writing code was that &lt;em&gt;&quot;if I get enough time to do it, I can hack it together and make it work&quot;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I realized that making things work the first time was &lt;strong&gt;easy&lt;/strong&gt;. It&apos;s just &lt;em&gt;brute force&lt;/em&gt;, really. &lt;/p&gt;
&lt;p&gt;But adding features to existing code? Making it work the second time, the third time and the &lt;strong&gt;fourth time&lt;/strong&gt;? Multiple iterations on something can be hard to do without introducing bugs.&lt;/p&gt;
&lt;p&gt;I should have changed it to &lt;em&gt;&quot;if I get enough time to do it, I can hack it together and make anything work [once]&quot;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In 180k-line JavaScript projects, I found it hard to iterate fast. Iterations and incremental improvements are what agile is all about. &lt;/p&gt;
&lt;p&gt;Eventually, I got tired of pushing out bugs to users and getting stuck in messes that I made myself. I realized something needed to change. &lt;/p&gt;
&lt;p&gt;I started learning TypeScript and studying &lt;strong&gt;software design&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;When we first start out coding, we often have little regard for &lt;u&gt;software design&lt;/u&gt;. &lt;/p&gt;
&lt;p&gt;Why should we? After we achieve dexterity with a programming language, we focus our efforts on fighting undefined errors, what &lt;em&gt;this&lt;/em&gt; means and several other annoying things.&lt;/p&gt;
&lt;p&gt;Not to mention, it&apos;s pretty challenging to enter the JavaScript world these days.&lt;/p&gt;
&lt;p&gt;JavaScript developers have a &lt;strong&gt;lot&lt;/strong&gt; on their plates to figure out as is (browsers, transpilation, build tools, and now TypeScript).&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;learning roadmap&lt;/strong&gt; for JavaScript developers can be a lot less streamlined than it  can be for Java and C# developers. &lt;/p&gt;
&lt;p&gt;So today, I&apos;m here to bring awareness on the subject of &lt;u&gt;design&lt;/u&gt; to JavaScript developers who won&apos;t tolerate the thought of writing another &lt;strong&gt;flimsy Node.js backend&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;We&apos;ve all done it, and it hurts... slowly.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In order to go fast, we need to go well&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think the answer is Uncle Bob&apos;s &lt;strong&gt;SOLID Principles&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;What-are-the-SOLID-Principles&quot; style=&quot;position:relative;&quot;&gt;What are the SOLID Principles?&lt;a href=&quot;#What-are-the-SOLID-Principles&quot; aria-label=&quot;What are the SOLID Principles permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The SOLID principles are a set of &lt;u&gt;software design principles&lt;/u&gt; that teach us how we can structure our functions and classes in order to be as &lt;u&gt;robust&lt;/u&gt;, &lt;u&gt;maintainable&lt;/u&gt; and &lt;u&gt;flexible&lt;/u&gt; as possible.&lt;/p&gt;
&lt;h4 id=&quot;Quick-history&quot; style=&quot;position:relative;&quot;&gt;Quick history&lt;a href=&quot;#Quick-history&quot; aria-label=&quot;Quick history permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The SOLID principles are a mnemonic acronym that were popularized by Robert C. Martin (Uncle Bob) in 2004-ish. They stand for:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#SRP&quot;&gt;S: Single Responsibility Principle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#OCP&quot;&gt;O: Open-Closed Principle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#LSP&quot;&gt;L: Liskov-Substitution Principle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#ISP&quot;&gt;I: Interface Segregation Principle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#DIP&quot;&gt;D: Dependency Inversion Principle&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;Primary-benefits&quot; style=&quot;position:relative;&quot;&gt;Primary benefits&lt;a href=&quot;#Primary-benefits&quot; aria-label=&quot;Primary benefits permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you ask me, the primary benefits of becoming well acquainted with the SOLID principles are that you&apos;ll learn how to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;write code that&apos;s testable&lt;/li&gt;
&lt;li&gt;write code that&apos;s easily understood&lt;/li&gt;
&lt;li&gt;write code where things are where they&apos;re expected to be&lt;/li&gt;
&lt;li&gt;write code where classes &lt;strong&gt;narrowly&lt;/strong&gt; do what they were intended to do&lt;/li&gt;
&lt;li&gt;write code that can be adjusted and extended quickly&lt;/li&gt;
&lt;li&gt;write code that can be adjusted and extended quickly without producing bugs&lt;/li&gt;
&lt;li&gt;write code that separates the &lt;em&gt;policy&lt;/em&gt; (rules) from the &lt;em&gt;details&lt;/em&gt; (implementation)&lt;/li&gt;
&lt;li&gt;write code that allows for implementations to be swapped out (think swapping out Email APIs, ORMs or web server frameworks)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So let&apos;s go through em!&lt;/p&gt;
&lt;h3 id=&quot;S-Single-Responsibilty-Principle&quot; style=&quot;position:relative;&quot;&gt;S: Single Responsibilty Principle&lt;a href=&quot;#S-Single-Responsibilty-Principle&quot; aria-label=&quot;S Single Responsibilty Principle permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;A class or function should only have one reason to change.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, instead of thinking that we should split code up because it would look cleaner in a single file, we split code up based on the &lt;u&gt;social structure&lt;/u&gt; of the users using it. Because that&apos;s what really dictates change.&lt;/p&gt;
&lt;p&gt;If we had an HR department, an Accounting department and an IT department in an enterprise application that calculates pay, and reports and saves hours, we&apos;d better make sure that we&apos;ve split up (or abstracted) the &lt;em&gt;operations most likely to change&lt;/em&gt; for each &lt;u&gt;each department&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;Here&apos;s an SRP &lt;em&gt;violation&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Employee&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculatePay&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement algorithm for hr, accounting and it&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reportHours&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement algorithm for hr, accounting and it&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement algorithm for hr, accounting and it&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is bad, very bad. The algorithm for each department is located in the &lt;strong&gt;same class&lt;/strong&gt;. If one department were to request a
change to one of their respective algorithms, it has the increased potential to ripple into another department&apos;s algorithm.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Making this work&lt;/em&gt; would require some nasty &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;switch&lt;/code&gt; statements.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Design Tip: If we see lots of code in switch statements, that should be a signal to us of a potential refactoring from a &lt;code class=&quot;language-text&quot;&gt;switch&lt;/code&gt; statement to several classes&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Employee&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// This needs to be implemented&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculatePay&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// This needs to be implemented&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reportHours&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// let&apos;s assume THIS is going to be the &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// same algorithm for each employee- it can&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// be shared here.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// common save algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HR&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Employee&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;calculatePay&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement own algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;reportHours&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement own algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Accounting&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Employee&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;calculatePay&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement own algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;reportHours&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// implement own algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IT&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Employee&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Much better. Each employee in this social structure has a single place where we can go to in order adjust their respective algorithm that is most likely to change.&lt;/p&gt;
&lt;p&gt;The key thing is to separate responsibility based on the &lt;strong&gt;social structure&lt;/strong&gt; of the users using the application.&lt;/p&gt;
&lt;h3 id=&quot;Open-Closed-Principle&quot; style=&quot;position:relative;&quot;&gt;Open-Closed Principle&lt;a href=&quot;#Open-Closed-Principle&quot; aria-label=&quot;Open Closed Principle permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Intially written about by Bertrand Meyer in the 1980s, Uncle Bob calls this the &quot;most important principle of object-oriented design&quot;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;A software artifact should be open for extension but closed for modification.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Generally, this principle is all about writing your code in such a way so that when you need to add new functionality, it shouldn&apos;t require changing the existing code. &lt;/p&gt;
&lt;p&gt;That&apos;s what we strive for in software architecture 😤. Being able to design your software so that the minimum amount of code needs to change in order to take it from point A to point B.&lt;/p&gt;
&lt;p&gt;To do this, we &lt;strong&gt;write interfaces and abstract classes&lt;/strong&gt; in order to dictate the &lt;strong&gt;higher-level policy&lt;/strong&gt; that needs to be implemented, and then we &lt;strong&gt;implement that policy&lt;/strong&gt; using &lt;a href=&quot;/wiki/concrete-class/&quot;&gt;concrete classes&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;Email-service-example&quot; style=&quot;position:relative;&quot;&gt;Email service example&lt;a href=&quot;#Email-service-example&quot; aria-label=&quot;Email service example permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Let&apos;s say that our boss told us that he wanted us to use SendGrid for sending emails.&lt;/p&gt;
&lt;p&gt;So we went and coded out a &lt;a href=&quot;/wiki/concrete-class/&quot;&gt;concrete&lt;/a&gt; &lt;code class=&quot;language-text&quot;&gt;SendGridService&lt;/code&gt; class, connecting to the Sendgrid API.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SendGridService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;sendgridInstance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sg &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; sendgridInstance&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; to&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// format the mail object to the sendgrid api shape&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// send it&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// create a result object &lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// return the result (success, failure, bounded, etc)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;3 months later he tells us that he wants us to use MailChimp instead because SendGrid is too expensive.&lt;/p&gt;
&lt;p&gt;So we go and code a &lt;a href=&quot;/wiki/concrete-class/&quot;&gt;concrete&lt;/a&gt; &lt;code class=&quot;language-text&quot;&gt;MailChimpService&lt;/code&gt;. But in order to hook it up, we&apos;re going to have to &lt;u&gt;change and potentially break&lt;/u&gt; a lot of code. &lt;/p&gt;
&lt;p&gt;How could we have designed that better?&lt;/p&gt;
&lt;p&gt;Following OCP, we could define an &lt;code class=&quot;language-text&quot;&gt;interface&lt;/code&gt; that specifies &lt;strong&gt;what&lt;/strong&gt; a mail service &lt;em&gt;can do&lt;/em&gt;, and leave the actual implementation to be figured out separately. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/solid/ocp-2.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;The main idea is to &lt;u&gt;keep the policy separate from the detail&lt;/u&gt; in order to enable loose coupling.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Higher level-components are protected from changes to lower level components.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This goes hand-in-hand with the &lt;strong&gt;&lt;a href=&quot;#DIP&quot;&gt;Dependency Inversion Principle&lt;/a&gt;&lt;/strong&gt; of depending on an interface instead of &lt;a href=&quot;/wiki/concrete-class/&quot;&gt;concretions&lt;/a&gt;, and closely with &lt;strong&gt;&lt;a href=&quot;#LSP&quot;&gt;Liskov Substitution Principle&lt;/a&gt;&lt;/strong&gt; in terms of being able to &lt;em&gt;swap out&lt;/em&gt; implementations as long as the same &lt;em&gt;type&lt;/em&gt;/&lt;em&gt;interface&lt;/em&gt; is being depended on.&lt;/p&gt;
&lt;h4 id=&quot;From-an-architectural-standpoint&quot; style=&quot;position:relative;&quot;&gt;From an architectural standpoint&lt;a href=&quot;#From-an-architectural-standpoint&quot; aria-label=&quot;From an architectural standpoint permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;This principle still makes a lot of sense when we think about the larger picture of software architecture.&lt;/p&gt;
&lt;p&gt;Imagine that this is some generic app where there&apos;s a controller that handles requests, passes it off to &lt;strong&gt;Use Case&lt;/strong&gt; (something that actually executes the business logic) and then maps the response into two different views for a Web App and a Mobile App.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/solid/ocp.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;What&apos;s the &lt;strong&gt;higher-level component&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;It&apos;s the Use Case!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/solid/ocp-1.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;If the Use Case were to change, it would likely affect the &lt;strong&gt;database&lt;/strong&gt;, the &lt;strong&gt;controller&lt;/strong&gt; and the &lt;strong&gt;data mappers&lt;/strong&gt; which create &lt;strong&gt;views&lt;/strong&gt; passed to web and mobile.&lt;/p&gt;
&lt;p&gt;But if the Web or Mobile View were to change, it&apos;s a lot less likely that that requirement will translate into something that affects the Use Case because the Use Case contains the &lt;u&gt;business logic and the entities&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;Again,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Higher level-components are protected from changes to lower level components.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;Liskov-Substition-Principle&quot; style=&quot;position:relative;&quot;&gt;Liskov-Substition Principle&lt;a href=&quot;#Liskov-Substition-Principle&quot; aria-label=&quot;Liskov Substition Principle permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Introduced by Barbara Liskov in the 1980s, she said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Let Φ(x) be a property provable about objects x of type T. Then Φ(y) should be true for objects y of type S where S is a subtype of T.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Admittedly, that&apos;s pretty confusing.&lt;/p&gt;
&lt;p&gt;The easiest way to explain it is that we should be able to swap one implementation for another.&lt;/p&gt;
&lt;p&gt;In Uncle Bob&apos;s &quot;Clean Architecture&quot;, he says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;To build software systems from interchangeable parts, those parts must adhere to a contract that allows those parts to be substituted one for another.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;He&apos;s talking about using &lt;strong&gt;interfaces&lt;/strong&gt; and &lt;strong&gt;abstract classes&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I think the &lt;strong&gt;Mail&lt;/strong&gt; example we gave a moment ago is the best way to think about this.&lt;/p&gt;
&lt;p&gt;Since we&apos;ve defined an &lt;code class=&quot;language-text&quot;&gt;IMailService&lt;/code&gt; interface:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; TransmissionResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Success&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Failure&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Bounced&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IEmailTransmissionResult&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  result&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TransmissionResult&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  message&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IMailService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IMail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IEmailTransmissionResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can implement various email services, as long as they implement the &lt;code class=&quot;language-text&quot;&gt;IMailService&lt;/code&gt; interface and the required &lt;code class=&quot;language-text&quot;&gt;sendMail(email: Mail)&lt;/code&gt; method.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SendGridEmailService&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IMailService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IMail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IEmailTransmissionResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MailChimpEmailService&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IMailService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IMail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IEmailTransmissionResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MailGunEmailService&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IMailService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IMail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IEmailTransmissionResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// algorithm&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then we can &lt;em&gt;&quot;Dependency Inject&quot;&lt;/em&gt; it into our classes, making sure we refer to the &lt;strong&gt;interface&lt;/strong&gt; it belongs to rather than one of the concrete implementations.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; emailService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IEmailService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;emailService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IEmailService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// like this 😇&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; emailService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeImpl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// handle request&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// send mail&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mail &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Mail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, all of these are valid.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mailGunService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MailGunEmailService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mailchimpService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MailChimpEmailService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sendgridService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SendGridEmailService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// any of these are valid &lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; createUserController &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mailGunService&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// or&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; createUserController &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mailchimpService&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// or&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; createUserController &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sendgridService&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Because we can interchange which implementation of an &lt;code class=&quot;language-text&quot;&gt;IEmailService&lt;/code&gt; we pass in, we&apos;re adhering to LSP.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;Interface-Segregation-Principle&quot; style=&quot;position:relative;&quot;&gt;Interface Segregation Principle&lt;a href=&quot;#Interface-Segregation-Principle&quot; aria-label=&quot;Interface Segregation Principle permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Prevent classes from relying on things that they dont need&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In order to prevent this, we should make sure to really &lt;u&gt;split up&lt;/u&gt; the unique functionality into interfaces.&lt;/p&gt;
&lt;p&gt;Ie: we &quot;segregate the interfaces&quot;.&lt;/p&gt;
&lt;p&gt;And we &lt;em&gt;should&lt;/em&gt;  be depending only on interfaces or abstract classes as per the &lt;strong&gt;the &lt;a href=&quot;#DIP&quot;&gt;Dependency Inversion Principle&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here&apos;s a famous example.&lt;/p&gt;
&lt;h4 id=&quot;The-3-user-operations-example&quot; style=&quot;position:relative;&quot;&gt;The 3 user operations example&lt;a href=&quot;#The-3-user-operations-example&quot; aria-label=&quot;The 3 user operations example permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Let&apos;s say we have 3 different &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; classes, that use 3 different methods on the same &lt;code class=&quot;language-text&quot;&gt;Operations&lt;/code&gt; class, and for each &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; class, we&apos;re depending on 2 additional operations that we don&apos;t need.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/solid/isp.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;For this, it might not seem like a big deal. But it could be a big deal if the constructor for the &lt;code class=&quot;language-text&quot;&gt;Operations&lt;/code&gt; class required us to inject all different kinds of dependencies in order to satisfy the other 2 operations that we didn&apos;t need.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Operations&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;U1Ops&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; U2Ops&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; U3Ops &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    emailService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IEmailService&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    authService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IAuthService&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    redisService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IRedisService&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// and more&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&apos;s when it&apos;s really a blaring no-no.&lt;/p&gt;
&lt;p&gt;This does occasionally end up with &lt;strong&gt;services&lt;/strong&gt; in &lt;a href=&quot;/articles/typescript-domain-driven-design/ddd-vs-crud-design/&quot;&gt;CRUD-first design&lt;/a&gt;, but to fix it, we can start by making sure that we rely on &lt;em&gt;abstractions&lt;/em&gt; to the things that we need.&lt;/p&gt;
&lt;p&gt;Like this...&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/blog/solid/isp-2.svg&quot;&gt;&lt;/p&gt;
&lt;p&gt;And then, if it were cumbersome to create the &lt;code class=&quot;language-text&quot;&gt;Operations&lt;/code&gt; class because it depended on so many things, taking &lt;code class=&quot;language-text&quot;&gt;User1&lt;/code&gt; for example, we would be able to create a class that ONLY implements &lt;code class=&quot;language-text&quot;&gt;U1Ops&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User1Operations&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;U1Ops&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userRepo&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IUserRepo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now &lt;code class=&quot;language-text&quot;&gt;User1&lt;/code&gt; only needs &lt;code class=&quot;language-text&quot;&gt;User1Operations&lt;/code&gt; and not all the other junk from &lt;code class=&quot;language-text&quot;&gt;Operations&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;Dependency-Inversion-Principle&quot; style=&quot;position:relative;&quot;&gt;Dependency Inversion Principle&lt;a href=&quot;#Dependency-Inversion-Principle&quot; aria-label=&quot;Dependency Inversion Principle permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Abstractions should not depend on details. Details should depend on abstractions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What&apos;s an abstraction again? An interface or abstract class.&lt;/p&gt;
&lt;p&gt;What&apos;s a detail again? A &lt;a href=&quot;/wiki/concrete-class/&quot;&gt;concrete class&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Abstractions should never depend on details. Ok, so that means, try not to do this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IMailService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// refering to concrete &quot;PrettyEmail&quot; and &quot;ShortEmailTransmissionResult&quot; from an abstraction&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PrettyEmail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ShortEmailTransmissionResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But instead, do this.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SendGridEmailService&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IMailService&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// concrete class relies on abstractions&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IMail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;IEmailTransmissionResult&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can normally tell when I&apos;m using an &lt;code class=&quot;language-text&quot;&gt;interface&lt;/code&gt; (at least in my code) from the Microsoft code style, which recommends that we prefix interfaces with an &quot;I&quot;. &lt;/p&gt;
&lt;p&gt;And this is already what you&apos;ve beeing seeing throughout this article so far! We&apos;ve been referring to abstractions (interfaces and abstract classes) instead of concrete ones. &lt;/p&gt;
&lt;h4 id=&quot;Main-components--detail-components&quot; style=&quot;position:relative;&quot;&gt;Main components / detail components&lt;a href=&quot;#Main-components--detail-components&quot; aria-label=&quot;Main components  detail components permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;We can&apos;t &lt;em&gt;never&lt;/em&gt; reference concrete classes. That&apos;s how we actually hook things up to get stuff to happen. &lt;/p&gt;
&lt;p&gt;Like &lt;a href=&quot;/articles/enterprise-typescript-nodejs/clean-consistent-expressjs-controllers/&quot;&gt;hooking up an express.js router&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// user/http/router/index.js&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; express &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;express&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Router &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;express&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CreateUserController &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../controllers&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; MailGunEmailService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../services&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mailGunService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MailGunEmailService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; createUserController &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mailGunService&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userRouter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Router&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

userRouter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/new&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; createUserController&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  userRouter
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We need to reference those concrete &lt;code class=&quot;language-text&quot;&gt;CreateUserController&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;MailGunEmailService&lt;/code&gt; classes in order to hook them up.&lt;/p&gt;
&lt;p&gt;But we &lt;em&gt;only&lt;/em&gt; do this to hook them up. Uncle Bob calls these &lt;strong&gt;Main components&lt;/strong&gt;. They&apos;re messy but they&apos;re necessary.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;However&lt;/strong&gt;, we shouldn&apos;t refer to concrete classes from another concrete class &lt;em&gt;directly&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This is what gives us the ability to &lt;strong&gt;test code&lt;/strong&gt;, because we leave the power to the implementor to pass in a &lt;strong&gt;mocked dependency&lt;/strong&gt; if we don&apos;t want to make API calls or rely on something we&apos;re not currently interested in testing.&lt;/p&gt;
&lt;p&gt;Therefore, do this.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; emailService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IEmailService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- abstraction&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;emailService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IEmailService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- abstraction&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; emailService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeImpl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// handle request&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// send mail&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mail &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Mail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Not this.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// we&apos;re limiting ourselves to a particlar concrete class.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; emailService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; SendGridService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- concretion&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;emailService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; SendGridService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- concretion&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; emailService&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeImpl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// handle request&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// send mail&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mail &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Mail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And &lt;em&gt;definitely&lt;/em&gt; not this.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; SendGridService &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../services&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- source code dependency&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// impossible to mock for tests&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; emailService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; SendGridService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SendGridService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- concretion&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeImpl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// handle request&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// send mail&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mail &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Mail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emailService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mail&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;Dependency-Injection-Frameworks&quot; style=&quot;position:relative;&quot;&gt;Dependency Injection Frameworks&lt;a href=&quot;#Dependency-Injection-Frameworks&quot; aria-label=&quot;Dependency Injection Frameworks permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;If hooking up dependencies to classes like this gets out of hand where there are &lt;em&gt;potentially hundreds of dependencies&lt;/em&gt;, we can look to a &lt;strong&gt;Dependency Injection Framework&lt;/strong&gt; to help resolve dependencies auto-magically.&lt;/p&gt;
&lt;p&gt;Although I haven&apos;t tried it, &lt;a href=&quot;http://inversify.io/&quot;&gt;Inversify&lt;/a&gt; seems to be the most popular one at the moment.&lt;/p&gt;
&lt;h4 id=&quot;More-on-Dependency-Inversion&quot; style=&quot;position:relative;&quot;&gt;More on Dependency Inversion&lt;a href=&quot;#More-on-Dependency-Inversion&quot; aria-label=&quot;More on Dependency Inversion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;If you&apos;re interested in a deeper dive, check out the &lt;a href=&quot;/wiki/dependency-inversion/&quot;&gt;wiki page&lt;/a&gt; on this principle.&lt;/p&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We just went through all of the SOLID principles. &lt;/p&gt;
&lt;p&gt;If you&apos;re using TypeScript, for you to really get the most out of your object-oriented software design efforts, I recommend re-reading this article a few times and referring back to it as you write TypeScript code, asking yourself &quot;is this SOLID&quot;?&lt;/p&gt;
&lt;p&gt;And if you&apos;re interested in having something you can download, I&apos;m putting together an &lt;a href=&quot;https://solidbook.io&quot;&gt;ebook&lt;/a&gt; (that&apos;s &lt;u&gt;free before its release&lt;/u&gt;) on applying the SOLID principles in Node.js and TypeScript. &lt;/p&gt;
&lt;p&gt;Definitely grab that if you&apos;re interested in having something you can print out.&lt;/p&gt;
&lt;h3 id=&quot;SOLID-JavaScript&quot; style=&quot;position:relative;&quot;&gt;SOLID JavaScript?&lt;a href=&quot;#SOLID-JavaScript&quot; aria-label=&quot;SOLID JavaScript permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Wow, we really talked a lot about interfaces, didn&apos;t we?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And you know what the sad part is?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Interfaces don&apos;t exist in JavaScript 😔&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which makes all of this a &lt;em&gt;whole lot harder&lt;/em&gt; to adhere to. &lt;/p&gt;
&lt;p&gt;That doesn&apos;t mean it&apos;s impossible to write SOLID JavaScript, it means that it will take a considerably increased amount of both discipline and attention to detail on our side. That&apos;s largely because we don&apos;t have the compiler on our side.&lt;/p&gt;
&lt;h3 id=&quot;Too-SOLID&quot; style=&quot;position:relative;&quot;&gt;Too SOLID?&lt;a href=&quot;#Too-SOLID&quot; aria-label=&quot;Too SOLID permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There&apos;s definitely a thing as &lt;em&gt;too SOLID&lt;/em&gt;. Writing clean code like this does increase the amount of files you introduce because you&apos;re writing abstractions for your concretions. &lt;/p&gt;
&lt;p&gt;If you&apos;re confident you&apos;ll never need to abstract something, consider making that trade-off for something more concrete-y.&lt;/p&gt;
&lt;h3 id=&quot;Additional-reading&quot; style=&quot;position:relative;&quot;&gt;Additional reading&lt;a href=&quot;#Additional-reading&quot; aria-label=&quot;Additional reading permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&quot;Clean Architecture&quot; by Uncle Bob&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Examples-of-SOLID-code&quot; style=&quot;position:relative;&quot;&gt;Examples of SOLID code&lt;a href=&quot;#Examples-of-SOLID-code&quot; aria-label=&quot;Examples of SOLID code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you&apos;re interested in seeing some SOLID code, particularly the &lt;code class=&quot;language-text&quot;&gt;Email&lt;/code&gt; example, check out &lt;a href=&quot;https://github.com/stemmlerjs/solid-email-microservice&quot;&gt;this repo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you&apos;re reading this and have really good repos of SOLID TypeScript or JavaScript code that you&apos;d like to share, reach out on Twitter and I&apos;ll include it.&lt;/p&gt;
&lt;hr&gt;</content:encoded></item><item><title><![CDATA[Flexible Error Handling w/ the Result Class | Enterprise Node.js + TypeScript]]></title><description><![CDATA[This article is part of the Enterprise Node.js + TypeScript series. Do you ever find yourself wondering where exactly you should throw an…]]></description><link>https://khalilstemmler.com/articles/enterprise-typescript-nodejs/handling-errors-result-class/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/enterprise-typescript-nodejs/handling-errors-result-class/</guid><pubDate>Wed, 15 May 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;This article is part of the &lt;strong&gt;&lt;a href=&quot;/articles/categories/enterprise-node-type-script/&quot;&gt;Enterprise Node.js + TypeScript&lt;/a&gt;&lt;/strong&gt; series&lt;/em&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Do you ever find yourself wondering where exactly you should throw an error to be consumed by a try-catch? Do you sometimes end up having multiple layers of try-catch blocks? Should you just return null instead?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you answered no, I&apos;d be &lt;em&gt;surprised&lt;/em&gt;. As a once new developer turned Junior Java Developer turned Node.js Developer turned TypeScript fanatic, I&apos;ve been there hundreds of times.&lt;/p&gt;
&lt;p&gt;Consider the creation of a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; object. We need to pass in several arguments that need to be validated in order to create one.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lastName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValidEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Email is invalid&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// .. validate firstName&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// .. validate lastName&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// return new user&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is a pretty common situation to be in. At this point, we might consider to ourselves, &quot;does it make sense to catch that error from within this class?&quot;. &lt;/p&gt;
&lt;p&gt;No, that doesn&apos;t make sense. What good is it to catch the creation error from within the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; class? It&apos;s entire purpose is be used by something else. And even still, what would we do? Return &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;? That&apos;s not a good idea. The calling code is expecting to get a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; back from this method. &lt;/p&gt;
&lt;p&gt;Ok, so that means that &lt;strong&gt;any class&apos;s&lt;/strong&gt; methods that create &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;s need to ensure that they wrap the creation of an &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; with a &lt;code class=&quot;language-text&quot;&gt;try-catch&lt;/code&gt; block.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I don&apos;t think that&apos;s a good way to go about things for an operation so trivial&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;Why-throwing-errors-purposefully-might-not-always-be-the-best-option&quot; style=&quot;position:relative;&quot;&gt;Why throwing errors purposefully might not always be the best option&lt;a href=&quot;#Why-throwing-errors-purposefully-might-not-always-be-the-best-option&quot; aria-label=&quot;Why throwing errors purposefully might not always be the best option permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Notice how careful I am about saying &lt;em&gt;&quot;might not always be the best option&quot;&lt;/em&gt;. That&apos;s because sometimes it is a good option. &lt;/p&gt;
&lt;p&gt;But if something like &lt;strong&gt;creating new objects&lt;/strong&gt; is this dangerous, it will impose constraints on the calling code. That&apos;s a &lt;strong&gt;code smell&lt;/strong&gt; if I ever smelt one.&lt;/p&gt;
&lt;p&gt;Another reason why we don’t want to do this is because using the &lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt; keyword isn&apos;t very type-safe. &lt;/p&gt;
&lt;p&gt;I know he &lt;a href=&quot;https://www.wired.co.uk/article/the-sonic-live-action-trailer-is-bad&quot;&gt;doesn&apos;t have great press these days&lt;/a&gt;, but I like to equate it to &lt;a href=&quot;https://en.wikipedia.org/wiki/Sonic_the_Hedgehog&quot;&gt;Sonic&lt;/a&gt; running through loops, picking up momentum, then stepping on something spiky, causing him to lose all his momentum and rings.&lt;/p&gt;
&lt;p&gt;When we use the &lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt; keyword, we&apos;re breaking the flow of our code and jumping up to the nearest Error handler (if it exists, and it better exist or else we&apos;ll get an uncaughtException error).&lt;/p&gt;
&lt;p&gt;This kind of &lt;em&gt;jumpy&lt;/em&gt; behaviour draws similarities to the &lt;a href=&quot;https://stackoverflow.com/questions/3329390/difference-between-goto-and-throw&quot;&gt;sometimes criticized&lt;/a&gt; &lt;code class=&quot;language-text&quot;&gt;GOTO&lt;/code&gt; statement.&lt;/p&gt;
&lt;p&gt;There are several arguments for and against that kind of behavior, but for our needs, we want &lt;strong&gt;predictable&lt;/strong&gt; and &lt;strong&gt;type safe&lt;/strong&gt; program behavior. That&apos;s one of the primary reasons why so many of us were drawn to TypeScript in the first place.&lt;/p&gt;
&lt;p&gt;Yes, you could &lt;em&gt;remember&lt;/em&gt; to put &lt;code class=&quot;language-text&quot;&gt;try-catch&lt;/code&gt; blocks all over the place and &lt;em&gt;predict&lt;/em&gt; what&apos;s going to happen, but again- the compiler isn&apos;t helping you at all on that. That&apos;s all on you.&lt;/p&gt;
&lt;h2 id=&quot;Introducing-the-Result-class&quot; style=&quot;position:relative;&quot;&gt;Introducing the Result class&lt;a href=&quot;#Introducing-the-Result-class&quot; aria-label=&quot;Introducing the Result class permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I first discovered the Result class while learning about &lt;a href=&quot;/wiki/anemic-domain-model/&quot;&gt;Anemic Domain Models&lt;/a&gt; in a pluralsight course by Vladimir Khorikov.&lt;/p&gt;
&lt;p&gt;This is his C# Result class, converted to TypeScript.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; isSuccess&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; isFailure&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; _value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;isSuccess&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isSuccess &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;InvalidOperation: A result cannot be 
        successful and contain an error&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isSuccess &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;InvalidOperation: A failing result 
        needs to contain an error message&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; isSuccess&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;freeze&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Cant retrieve the value from a failed result.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;combine&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;results&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; result &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; results&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There&apos;s many benefits to using this class. It allows us to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;safely return error states&lt;/li&gt;
&lt;li&gt;return valid results&lt;/li&gt;
&lt;li&gt;combine several results and determine the overall success or failure states&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With a new &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt; instance, we can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;check for validity with &lt;code class=&quot;language-text&quot;&gt;isSuccess&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;check for failure using the &lt;code class=&quot;language-text&quot;&gt;isFailure&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;collect the error with &lt;code class=&quot;language-text&quot;&gt;error&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;collect the value with &lt;code class=&quot;language-text&quot;&gt;getValue()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;check for the validity of an array of &lt;code class=&quot;language-text&quot;&gt;Result&lt;/code&gt;s using &lt;code class=&quot;language-text&quot;&gt;Result.combine(results: Result[])&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;Using-the-Result-class&quot; style=&quot;position:relative;&quot;&gt;Using the Result class&lt;a href=&quot;#Using-the-Result-class&quot; aria-label=&quot;Using the Result class permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&apos;s adjust the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; class, returning a &lt;code class=&quot;language-text&quot;&gt;Result&amp;lt;User&amp;gt;&lt;/code&gt; from the static &lt;code class=&quot;language-text&quot;&gt;createUser()&lt;/code&gt; &lt;strong&gt;Factory method&lt;/strong&gt; instead of throwing an error explicitly.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lastName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValidEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Email is invalid&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;firstName &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;First name is invalid&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;lastName &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; lastName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; lastName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fail&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Last name is invalid&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Note: Another potential refactoring would be to locate the validation rules in &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;Value Objects&lt;/a&gt; for &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;firstName&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;lastName&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;And then let&apos;s actually create a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; from a parent class.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeImpl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; req &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// persist to database ...&lt;/span&gt;
    
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Voila!&lt;/p&gt;
&lt;p&gt;And if we were using &lt;a href=&quot;/articles/typescript-value-object/&quot;&gt;Value Objects&lt;/a&gt;, we could use the &lt;code class=&quot;language-text&quot;&gt;Result.combine()&lt;/code&gt; method to validate an array of &lt;code class=&quot;language-text&quot;&gt;Result&lt;/code&gt;s all at once like this..&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CreateUserController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeImpl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; req &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; email&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emailOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Email&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; firstNameOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;FirstName&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FirstName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;firstName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; lastNameOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;LastName&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; LastName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lastName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userPropsResult&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;combine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; 
      emailOrError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; firstNameOrError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastNameOrError
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// If this failed, it will return the first error that occurred.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userPropsResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userPropsResult&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userOrError&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Result&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      emailOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
      firstNameOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
      lastNameOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isFailure&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userOrError&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// persist to database ...&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&apos;s it! That&apos;s how we can use a &lt;code class=&quot;language-text&quot;&gt;Result&lt;/code&gt; class to allow the compiler to help us deal with expected edge cases errors.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;There are some cases where throwing errors purposefully does make a lot of sense though!&lt;/p&gt;
&lt;h2 id=&quot;When-to-throw-errors-purposefully&quot; style=&quot;position:relative;&quot;&gt;When to throw errors purposefully&lt;a href=&quot;#When-to-throw-errors-purposefully&quot; aria-label=&quot;When to throw errors purposefully permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;A: When you&apos;re working on a library or a tool to be used by other developers. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In this case, you don&apos;t want to force them into catching errors using our preferred &lt;code class=&quot;language-text&quot;&gt;Result&lt;/code&gt; class or any other non-standard approach. We should leave that up to them.&lt;/p&gt;
&lt;p&gt;Although, in the JavaScript world, a common convention is to return errors as the &lt;em&gt;first parameter&lt;/em&gt; to a callback. &lt;/p&gt;
&lt;h3 id=&quot;Example-Wrapping-callback-errors-as-rejected-Promises&quot; style=&quot;position:relative;&quot;&gt;Example: Wrapping callback errors as rejected Promises&lt;a href=&quot;#Example-Wrapping-callback-errors-as-rejected-Promises&quot; aria-label=&quot;Example Wrapping callback errors as rejected Promises permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The developers who implemented the &lt;a href=&quot;https://www.npmjs.com/package/redis&quot;&gt;Redis&lt;/a&gt; npm package decided that they wanted to report back errors using the callback approach.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Error&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reply&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// handle error&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// handle reply&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In my actual application code consuming this library, I&apos;ll usually wrap these in a &lt;code class=&quot;language-text&quot;&gt;Promise&lt;/code&gt;s to be used by the rest of my code with async/await.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; RedisClient &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;redis&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AbstractRedisClient&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; client&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; RedisClient&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;client&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; RedisClient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;client &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; client&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; getOne&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
         &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Error&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reply&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;reply&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When you&apos;re dealing with APIs, external resources or other adapters to the outside world, it&apos;s a pretty common thing to need to create your own &lt;strong&gt;Adapter&lt;/strong&gt; for using it so that you can safely refer to it from within your own codebase using your &lt;strong&gt;own code style&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;But, it wouldn&apos;t be clean to need to create an &lt;strong&gt;Adapter&lt;/strong&gt; for each class (like the &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; class) in order to safely wrap them... so we needed something else.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;B: When we encounter errors that we don&apos;t expect or know how to deal with. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Kind of an extension to &lt;code class=&quot;language-text&quot;&gt;A&lt;/code&gt; because when we&apos;re working on library code, we &lt;strong&gt;don&apos;t really know&lt;/strong&gt; how people using our code in the future will plan to handle errors, we &lt;strong&gt;just need them to know that they&apos;re happening&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For errors that we &lt;strong&gt;don&apos;t know how to deal with&lt;/strong&gt;, usually, we would like to cancel the operation that was taking place because something bad happened. &lt;/p&gt;
&lt;p&gt;These are errors that really mess up what we were trying to do and can be caused by an infinite possibility of things that we didn&apos;t expect or assume would happen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;database connectivity issues&lt;/li&gt;
&lt;li&gt;code typos&lt;/li&gt;
&lt;li&gt;null pointer errors (sometimes)&lt;/li&gt;
&lt;li&gt;out of memory&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If it&apos;s an &lt;u&gt;http request&lt;/u&gt;, we might throw back a &lt;code class=&quot;language-text&quot;&gt;500&lt;/code&gt; error to the client.&lt;/p&gt;
&lt;p&gt;If it&apos;s a &lt;u&gt;script&lt;/u&gt;, we might exit with a non-zero error code.&lt;/p&gt;
&lt;p&gt;Or, yes use a &lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt; statement, but only when you&apos;re writing code to be used by someone else that you have no idea how they intend to use it.&lt;/p&gt;
&lt;p&gt;In this case, it truly makes sense for us to kill whatever it was we were doing and just exit or cancel the web request.&lt;/p&gt;
&lt;h2 id=&quot;Conclusion&quot; style=&quot;position:relative;&quot;&gt;Conclusion&lt;a href=&quot;#Conclusion&quot; aria-label=&quot;Conclusion permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Some developers can get really really fancy with this. I personally haven&apos;t done too much research on the topic myself, but it stems from &lt;a href=&quot;https://en.wikipedia.org/wiki/Monad_(functional_programming)&quot;&gt;monads&lt;/a&gt; and the like and you can get some really funky rxjs-y like results if you took this to the extreme.&lt;/p&gt;
&lt;p&gt;I don&apos;t think that way of programming is mainstream enough for me to want to advocate it to my peers too intently just yet, as even Rx.js can sometimes be a challenge. Perhaps at some point I&apos;ll find time to learn more.&lt;/p&gt;
&lt;h2 id=&quot;Additional-reading&quot; style=&quot;position:relative;&quot;&gt;Additional reading&lt;a href=&quot;#Additional-reading&quot; aria-label=&quot;Additional reading permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here are some more really good resources on this topic if you&apos;d like to go deeper.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://enterprisecraftsmanship.com/2015/03/20/functional-c-handling-failures-input-errors/&quot;&gt;Functional C#: Handling failures, input errors&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.engineerspock.com/2016/10/24/handling-error-and-exceptions-part-3/&quot;&gt;Handling Errors and Exceptions in C#. Part 3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://dev.to/_gdelgado/type-safe-error-handling-in-typescript-1p4n&quot;&gt;Type Safe Error Handling in TypeScript&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[REST-first design is Imperative, DDD is Declarative [Comparison] - DDD w/ TypeScript]]></title><description><![CDATA[Also from the Domain-Driven Design with TypeScript series. When you get a new Node.js project, what do you start coding first? Do you start…]]></description><link>https://khalilstemmler.com/articles/typescript-domain-driven-design/ddd-vs-crud-design/</link><guid isPermaLink="false">https://khalilstemmler.com/articles/typescript-domain-driven-design/ddd-vs-crud-design/</guid><pubDate>Wed, 15 May 2019 15:04:10 GMT</pubDate><content:encoded>&lt;p class=&quot;course-cta&quot;&gt;
We cover this topic in &lt;a href=&quot;https://www.essentialist.dev/master-the-essentials-of-software-design-with-typescript&quot;&gt;The Software Essentialist&lt;/a&gt; online course. Check it out if you liked this post.
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Also from the &lt;strong&gt;&lt;a href=&quot;/articles/categories/domain-driven-design/&quot;&gt;Domain-Driven Design with TypeScript&lt;/a&gt;&lt;/strong&gt; series&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;When you get a new Node.js project, what do you start coding first?&lt;/p&gt;
&lt;p&gt;Do you start with the &lt;strong&gt;database schema&lt;/strong&gt;? &lt;/p&gt;
&lt;p&gt;Do you start with the &lt;strong&gt;RESTful API&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;Do you start with the &lt;strong&gt;Models&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;REST-first Design&lt;/em&gt; is a term I&apos;ve been using it to describe the difference between what &lt;a href=&quot;/articles/domain-driven-design-intro/&quot;&gt;Domain-Driven Design&lt;/a&gt; projects and REST-first CRUD projects look like on a code level.&lt;/p&gt;
&lt;p&gt;Just for reminders, REST stands for &quot;Representational State Transfer&quot;, which is a architectural style towards designing APIs on the web with HTTP. &lt;/p&gt;
&lt;p&gt;In this article, I&apos;m going to explain what a &lt;strong&gt;REST-first Designed&lt;/strong&gt; codebase looks like, how it&apos;s &lt;strong&gt;imperative&lt;/strong&gt; and how it differs from a &lt;strong&gt;Domain-Driven Designed&lt;/strong&gt; project.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;Imperative-vs-Declarative&quot; style=&quot;position:relative;&quot;&gt;Imperative vs. Declarative&lt;a href=&quot;#Imperative-vs-Declarative&quot; aria-label=&quot;Imperative vs Declarative permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Do we remember what &lt;strong&gt;imperative&lt;/strong&gt; code is? &lt;/p&gt;
&lt;h3 id=&quot;Imperative&quot; style=&quot;position:relative;&quot;&gt;Imperative&lt;a href=&quot;#Imperative&quot; aria-label=&quot;Imperative permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You’ve probably written a lot of &lt;strong&gt;imperative&lt;/strong&gt; code in your life, it’s usually the first thing we start out learning when we get into programming.&lt;/p&gt;
&lt;p&gt;Imperative code is primarily concerned with &lt;em&gt;&quot;how&quot;&lt;/em&gt; we do something. We need to be very explicit for how the program&apos;s state gets changed.&lt;/p&gt;
&lt;h4 id=&quot;Find-the-max-number-in-an-array-Imperative&quot; style=&quot;position:relative;&quot;&gt;Find the max number in an array [Imperative]&lt;a href=&quot;#Find-the-max-number-in-an-array-Imperative&quot; aria-label=&quot;Find the max number in an array Imperative permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Here&apos;s an example of how we would determine the &lt;strong&gt;max&lt;/strong&gt; number in an array of numbers, imperative style.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; numbers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; max &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; numbers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;numbers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; max&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;   
    max &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; numbers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; 
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Because imperative programming requires you to specify the exact commands to specify &quot;how&quot; program state changes, in this example, we:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;have a list of numbers&lt;/li&gt;
&lt;li&gt;create a for loop starting at 0 &lt;/li&gt;
&lt;li&gt;increment i up to numbers.length&lt;/li&gt;
&lt;li&gt;and if number at the current index is greater than the max, then we’ll set that as the max&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&apos;m sure you know how to code 😊 but I figured I&apos;d list out every step to be succinct that this is what we do with imperative code. We define the &lt;em&gt;&quot;how&quot;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;REST-first Design&lt;/strong&gt; often ends up being imperative by nature. We&apos;ll look closer at that statement in a few moments.&lt;/p&gt;
&lt;h3 id=&quot;Declarative&quot; style=&quot;position:relative;&quot;&gt;Declarative&lt;a href=&quot;#Declarative&quot; aria-label=&quot;Declarative permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Declarative programming is more concerned about the &lt;em&gt;“what”&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Because of this, declarative code is a bit more &lt;em&gt;&quot;wordy&quot;&lt;/em&gt; and abstracts away a lot of the details for expressability.&lt;/p&gt;
&lt;p&gt;Let&apos;s look at the same example.&lt;/p&gt;
&lt;h4 id=&quot;Find-the-max-number-in-an-array-Declarative&quot; style=&quot;position:relative;&quot;&gt;Find the max number in an array [Declarative]&lt;a href=&quot;#Find-the-max-number-in-an-array-Declarative&quot; aria-label=&quot;Find the max number in an array Declarative permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; numbers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; max &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; numbers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Take particular notice of the &lt;strong&gt;language&lt;/strong&gt; being used in this example.&lt;/p&gt;
&lt;p&gt;Ask yourself,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;which of the two examples would non-programmers be quicker to understand?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Notice that in this example, the &lt;strong&gt;language&lt;/strong&gt; better describes the &lt;em&gt;“what”&lt;/em&gt; than the imperative equivalent? &lt;/p&gt;
&lt;p&gt;That’s the beauty of declarative programming. Code is much more readable and program intent is easier understood (if operations are appropriately named).&lt;/p&gt;
&lt;p&gt;Declarative style code is one of the primary benefits of designing software using &lt;strong&gt;Domain-Driven Design&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Now that we&apos;re refreshed on &lt;strong&gt;Imperative&lt;/strong&gt; and &lt;strong&gt;Declarative&lt;/strong&gt; style coding, we&apos;ll dive deeper into my statements.&lt;/p&gt;
&lt;h2 id=&quot;REST-first-Design&quot; style=&quot;position:relative;&quot;&gt;REST-first Design&lt;a href=&quot;#REST-first-Design&quot; aria-label=&quot;REST first Design permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When we build RESTful applications, we tend to think more about designing our applications from either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the database up and&lt;/li&gt;
&lt;li&gt;the API calls up&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because of this, there&apos;s a tendency to place the majority of our business logic in either controllers or &lt;strong&gt;services&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;You might remember from Uncle Bob&apos;s &quot;Clean Architecture&quot;, for controllers this is definitely  no-no.&lt;/p&gt;
&lt;p&gt;And if you read his book of the same name, you might recall the &lt;em&gt;potential&lt;/em&gt; service-oriented fallacy of putting all the domain logic into services (hint: &lt;a href=&quot;/wiki/anemic-domain-model/&quot;&gt;Anemic Domain Models&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;But this is the type of code that gets written when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;we want to get something up and running quickly&lt;/li&gt;
&lt;li&gt;we use a framework, such as &lt;a href=&quot;https://nestjs.com/&quot;&gt;Nest.js&lt;/a&gt;, holistically&lt;/li&gt;
&lt;li&gt;we want to respond to prototype apps&lt;/li&gt;
&lt;li&gt;we&apos;re working on small apps&lt;/li&gt;
&lt;li&gt;we&apos;re working on problems that are either #1 or #2 from the &lt;a href=&quot;/wiki/3-categories-of-hard-software-problems/&quot;&gt;Hard Software Problems&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And it does suffice for a large number projects!&lt;/p&gt;
&lt;p&gt;However, for complex domains with complicated business rules and policies, this has the potential to become incredibly difficult to change and extend as time goes on.&lt;/p&gt;
&lt;p&gt;In REST-first CRUD applications, we almost solely &lt;strong&gt;write imperative code to satisfy business use cases&lt;/strong&gt;. Let&apos;s take a look at what that looks like.&lt;/p&gt;
&lt;h3 id=&quot;REST-first-code&quot; style=&quot;position:relative;&quot;&gt;REST-first code&lt;a href=&quot;#REST-first-code&quot; aria-label=&quot;REST first code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let’s say we were working on an application where &lt;code class=&quot;language-text&quot;&gt;Customers&lt;/code&gt; could rent &lt;code class=&quot;language-text&quot;&gt;Movies&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;Designing REST-first using &lt;a href=&quot;https://expressjs.com/&quot;&gt;Express.js&lt;/a&gt; and the &lt;a href=&quot;http://docs.sequelizejs.com/&quot;&gt;Sequelize ORM&lt;/a&gt;, my code might look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MovieController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rentMovie&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;movieId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; customerId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Sequelize ORM models&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Movie&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Customer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; RentedMovie&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CustomerCharge &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Get the raw orm records from Sequelize&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; movie &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Movie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; movie_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; movieId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; customer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Customer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; customer_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; customerId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// 401 error if not found&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;movie &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;notFound&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Movie not found&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// 401 error if not found&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;customer &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;notFound&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Customer not found&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Create a record which signified a movie was rented&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; RentedMovie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      customer_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; customerId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      movie_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; movieId
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Create a charge for this customer.&lt;/span&gt;
	  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; CustomerCharge&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; movie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rentPrice
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this code example, we pass in a &lt;code class=&quot;language-text&quot;&gt;movieId&lt;/code&gt; and a &lt;code class=&quot;language-text&quot;&gt;customerId&lt;/code&gt;, then pull out the appropriate Sequelize models that we know we’re going to need to use. We do a quick null check and then if both model instances are returned, we’ll create a &lt;code class=&quot;language-text&quot;&gt;RentedMovie&lt;/code&gt; and a &lt;code class=&quot;language-text&quot;&gt;CustomerCharge&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is quick and dirty and it shows you just how quickly we can get things up and running REST-first. &lt;/p&gt;
&lt;p&gt;But things start to get challenging as soon as we add &lt;strong&gt;business rules&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&quot;Business-Rules-in-CRUD-first-code&quot; style=&quot;position:relative;&quot;&gt;Business Rules in CRUD-first code&lt;a href=&quot;#Business-Rules-in-CRUD-first-code&quot; aria-label=&quot;Business Rules in CRUD first code permalink&quot; class=&quot;link-icon after&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; height=&quot;20&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Let’s add some constraints to this. Consider that &lt;code class=&quot;language-text&quot;&gt;Customer&lt;/code&gt; isn&apos;t allowed to rent a movie if they:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A) have rented the maximum amount of movies at one time (3, but this is configurable)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;B) have unpaid balances.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;How exactly can we enforce this business logic? &lt;/p&gt;
&lt;p&gt;A primitive approach would be to enforce it directly in our &lt;code class=&quot;language-text&quot;&gt;MovieController&lt;/code&gt;’s &lt;code class=&quot;language-text&quot;&gt;purchaseMovie&lt;/code&gt; method like so.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MovieController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rentMovie&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; req &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; movieId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;movie&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; customerId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;customer&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// We need to pull out one more model,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// CustomerPayment&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
      Movie&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
      Customer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
      RentedMovie&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
      CustomerCharge&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
      CustomerPayment 
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; movie &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Movie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; movie_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; movieId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; customer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Customer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; customer_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; customerId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;movie &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;notFound&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Movie not found&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;customer &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;notFound&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Customer not found&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Get the number of movies that this user has rented&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rentedMovies &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; RentedMovie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; customer_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; customerId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; numberRentedMovies &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; rentedMovies&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Enforce the rule&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;numberRentedMovies &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Customer already has the maxiumum number of rented movies&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Get all the charges and payments so that we can &lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// determine if the user still owes money&lt;/span&gt;
  