<?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" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[The Sunshine Layer]]></title><description><![CDATA[Pierce through cloudy concepts of software development with weekly practical insights on programming principles, system design and more.]]></description><link>https://www.thesunshinelayer.com</link><image><url>https://substackcdn.com/image/fetch/$s_!16TC!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F305aae40-8801-4326-bdd2-a799967261a0_500x500.png</url><title>The Sunshine Layer</title><link>https://www.thesunshinelayer.com</link></image><generator>Substack</generator><lastBuildDate>Mon, 04 May 2026 10:50:37 GMT</lastBuildDate><atom:link href="https://www.thesunshinelayer.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[The Sunshine Layer]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[thesunshinelayer@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[thesunshinelayer@substack.com]]></itunes:email><itunes:name><![CDATA[Elena Sunshine]]></itunes:name></itunes:owner><itunes:author><![CDATA[Elena Sunshine]]></itunes:author><googleplay:owner><![CDATA[thesunshinelayer@substack.com]]></googleplay:owner><googleplay:email><![CDATA[thesunshinelayer@substack.com]]></googleplay:email><googleplay:author><![CDATA[Elena Sunshine]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[The ball and the bat problem]]></title><description><![CDATA[Why a bug is Never just a 5-minute fix]]></description><link>https://www.thesunshinelayer.com/p/the-ball-and-the-bat-problem</link><guid isPermaLink="false">https://www.thesunshinelayer.com/p/the-ball-and-the-bat-problem</guid><dc:creator><![CDATA[Elena Sunshine]]></dc:creator><pubDate>Mon, 20 May 2024 06:01:19 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/d2624d2e-6e26-4d89-b761-815b10450e5e_4200x3000.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let's solve a small math puzzle. Consider this problem: You have a bat and a ball, which together cost 1.1 euros. The bat costs 1 euro more than the ball.</p><p><strong>How much does the ball cost?</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UXd_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7e547-aa9f-4406-aedc-f661f042268b_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UXd_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7e547-aa9f-4406-aedc-f661f042268b_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!UXd_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7e547-aa9f-4406-aedc-f661f042268b_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!UXd_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7e547-aa9f-4406-aedc-f661f042268b_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!UXd_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7e547-aa9f-4406-aedc-f661f042268b_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UXd_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7e547-aa9f-4406-aedc-f661f042268b_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8ec7e547-aa9f-4406-aedc-f661f042268b_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:351263,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!UXd_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7e547-aa9f-4406-aedc-f661f042268b_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!UXd_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7e547-aa9f-4406-aedc-f661f042268b_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!UXd_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7e547-aa9f-4406-aedc-f661f042268b_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!UXd_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ec7e547-aa9f-4406-aedc-f661f042268b_2380x2380.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The immediate answer might be 10 cents. If you jumped to that conclusion, well&#8230; you&#8217;re wrong.</p><p>If the ball were 10 cents, the bat would be 1.1 euros, making the total 1.2 euros, not 1.1 euros.</p><p>Let's dive into the math instead:</p><p>&#119909;+(&#119909;+1)=1.10</p><p>2&#119909;+1=1.10</p><p>2&#119909;=0.10</p><p><strong>&#119909;=0.05</strong></p><p>So, the ball costs 5 cents, and the bat costs 1.05 euros.</p><p>This puzzle shows how easy it is to make wrong assumptions based on a superficial understanding. It mirrors the challenges we face as developers when underestimating the complexity of tasks. This isn't just a party trick. It's a powerful metaphor for understanding the pitfalls of estimations.</p><h2><strong>The 5-Minute Fix Myth</strong></h2><p>I bet you've experienced that moment when a new bug pops up. You quickly glance at the issue and happily say to yourself, &#8220;Oh, that&#8217;s easy. It&#8217;ll take 5 minutes.&#8221; You might even express this out loud, making a commitment to stakeholders.</p><p>Yet, what appears to be a simple fix often spirals into a complex ordeal, spanning multiple aspects of your domain.</p><p>Let's face it. <strong>It never is just a 5-minute fix.</strong></p><p>Did you consider the time required to write tests for that bug to never happen again? Did you consider regressions? Could this fix potentially affect the performance of the application? Is it backwards compatible with previous versions of the application? Did you think about the pipeline's running time? The deployment time? What about documentation that needs updating?</p><p>Every developer has had the experience of diving into what seemed like a simple issue only to find themselves tangled in a web of dependencies and unforeseen problems. It's a rite of passage in the world of software development. We often underestimate the true scope of tasks because of overconfidence or a desire to demonstrate efficiency. But, as the bat and ball puzzle illustrates, our initial assumptions are often flawed.</p><p></p><p>Now, don&#8217;t get me wrong. I'm not advocating for discussing <em><strong>every</strong></em> minute task. Sometimes, a change is truly trivial.</p><p>I even have <strong>a counterexample puzzle</strong> to demonstrate my point.</p><p>Let's consider two trains that are 100 kilometers apart and move towards each other. One train travels at 40 km/h, and the other at 60 km/h. A bird starts flying from the first train at 90 km/h towards the second train, then turns around immediately upon reaching the second train and flies back to the first train, and so on, until the trains collide.</p><p><strong>How far has the bird flown?</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ud6Z!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b86aed-b6b9-403b-aee4-aa9f2a22ab9b_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ud6Z!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b86aed-b6b9-403b-aee4-aa9f2a22ab9b_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!Ud6Z!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b86aed-b6b9-403b-aee4-aa9f2a22ab9b_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!Ud6Z!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b86aed-b6b9-403b-aee4-aa9f2a22ab9b_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!Ud6Z!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b86aed-b6b9-403b-aee4-aa9f2a22ab9b_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ud6Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b86aed-b6b9-403b-aee4-aa9f2a22ab9b_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d8b86aed-b6b9-403b-aee4-aa9f2a22ab9b_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:388858,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ud6Z!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b86aed-b6b9-403b-aee4-aa9f2a22ab9b_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!Ud6Z!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b86aed-b6b9-403b-aee4-aa9f2a22ab9b_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!Ud6Z!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b86aed-b6b9-403b-aee4-aa9f2a22ab9b_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!Ud6Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b86aed-b6b9-403b-aee4-aa9f2a22ab9b_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The first instinct is to sum up the infinite series of the bird's flights.</p><p>Instead, it's much simpler than that.</p><p>You just need to realize the trains take 1 hour to meet (100 kilometers / (40+60) km/h), and the bird flies for that hour at 90 km/h. So, the <strong>bird flies 90 kilometers</strong>.</p><p>This puzzle illustrates that sometimes, the problem isn't as complex as it seems. The key is knowing when to dig deeper and when to take things at face value.</p><h2><strong>Strategies to Mitigate Risks</strong></h2><p>So, how do we tackle this? It seems we&#8217;re stuck in between cognitive biases. Here are some strategies to mitigate the risks:</p><h3><strong>1. Challenge Your First Instinct</strong></h3><p>Conduct a brief risk assessment or a quick review with a teammate to uncover potential hidden complexities. Don&#8217;t underestimate the power of a second pair of eyes. This can help identify aspects that might not be immediately obvious and prevent underestimation of the task at hand.</p><h3><strong>2. Timeboxed Spikes</strong></h3><p>If the uncertainty is high, as it often is when starting new projects or integrating with new services, do a timeboxed spike. This means allocating a fixed amount of time to explore the problem space, gather information, and identify potential pitfalls. This helps in making more informed decisions and estimates.</p><h3><strong>3. Break Down the Task</strong></h3><p>Break down the task into smaller components. Eat the elephant one bite at a time. This way, you're more likely to reveal complexities that weren't apparent initially. Smaller tasks are easier to manage, track, and estimate accurately. It also helps in identifying dependencies and potential bottlenecks early.</p><h3><strong>4. Plan for Multiple Iterations</strong></h3><p>Recognize that the first fix may not be the final one. Plan for multiple iterations, including testing and feedback cycles. Continuous integration and deployment practices can help in catching issues early and often, reducing the risk of large, unforeseen problems.</p><h3><strong>5. Embrace Code Reviews and Pair Programming</strong></h3><p>Overconfidence in personal coding abilities might lead some developers to dismiss the possibility of errors in their own code, overlooking simple solutions. That&#8217;s where implementing practices such as thorough code reviews and pair programming comes in handy. These techniques foster continuous learning and humility, and also provide a fresh perspective on the problem, potentially uncovering issues that might have been overlooked.</p><h3><strong>6. Encourage Team Discussions</strong></h3><p>When a miscalculation happens, it&#8217;s important to realize it's not the end of the world. Encourage team discussions about mistakes and learning opportunities from past bugs to cultivate a more accurate assessment of debugging tasks. It's through sharing, how we grow the most. Learning from past experiences and sharing those learnings with the team can help in avoiding similar pitfalls in the future.</p><h3><strong>7. Document Your Findings</strong></h3><p>Effective documentation is crucial for maintaining clarity and continuity in software projects. When the entire team contributes to and utilizes documentation, it ensures comprehensive coverage and accessibility of information. Establish a documentation protocol where each team member contributes to the document creation and review process. Good documentation practices ensure that knowledge is not lost and can be easily transferred within the team.</p><h3><strong>8. Keep a Short Feedback Loop</strong></h3><p>Sometimes it's easy to drill deep and develop a new feature based on unconscious assumptions about what the end result should look like. By keeping the feedback loop short, you get the chance to clear them out. Regular check-ins and reviews with stakeholders can ensure that the development is on the right track and aligns with the requirements.</p><h3><strong>9. Foster a Culture of Continuous Learning</strong></h3><p>It&#8217;s important that both you and your colleagues engage in continuous learning. It can be anything, from the official training sessions, workshops or attending conferences, to more informal, brownbag sessions, reading club, or simple &#8220;this week I learned&#8221; trivia. Staying updated with the best practices in the industry oftentimes provides new insights and tools that can be applied to solve complex problems more efficiently.</p><h3><strong>10. Use Automated Tools and Techniques</strong></h3><p>If you've been following this newsletter, you probably saw this one coming. Leverage the power of unit testing, continuous integration, and continuous deployment tools to streamline the development process. Automated tools can help in identifying issues early and ensure that the codebase remains stable, reducing the time spent on manual testing and debugging.</p><h2><strong>Conclusion</strong></h2><p>When it comes to quick fixes, what seems like a 5-minute fix rarely is (if ever). By challenging your first instinct, conducting brief risk assessments, breaking down tasks, planning for multiple iterations, embracing code reviews, encouraging team discussions, documenting findings, and keeping a short feedback loop, you can better navigate the complexities and uncertainties inherent in development tasks.</p><p>Moreover, effective communication, fostering a culture of continuous learning, and leveraging automated tools can further enhance your team's ability to handle complex problems efficiently. By adopting these strategies, you can mitigate the risks associated with underestimating or overestimating tasks and ensure a smoother development process.</p><div><hr></div><h1>Pay it forward</h1><p>Here are this edition&#8217;s knowledge nuggets that made me pause and think:</p><p><a href="https://newsletter.systemdesign.one/p/payment-gateway-architecture?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">How Razorpay Scaled to Handle Flash Sales at 1500 Requests per Second</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Neo Kim&quot;,&quot;id&quot;:135589200,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c103940f-0d8b-47e7-9a33-013202e17bb8_389x389.jpeg&quot;,&quot;uuid&quot;:&quot;f9c22633-b145-4092-8af4-5059c91b0bd6&quot;}" data-component-name="MentionToDOM"></span> </p><p><a href="https://systemdesignclassroom.substack.com/p/latency-is-a-silent-killer">Latency is a silent killer</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Raul Junco&quot;,&quot;id&quot;:98661477,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/45a92f5e-1e2e-4dfa-9ff3-45fc5ad0c57e_612x612.png&quot;,&quot;uuid&quot;:&quot;70c31275-32b4-4356-bc75-da86c5b55eef&quot;}" data-component-name="MentionToDOM"></span></p><p><a href="https://jadecodes.substack.com/p/when-agile-isnt-agile">When Agile, isn't agile</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Jade Wilson&quot;,&quot;id&quot;:199051090,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/98108c42-35f4-479c-b526-096d180d5288_625x625.jpeg&quot;,&quot;uuid&quot;:&quot;7ee45fef-e370-4125-94f1-cc0c493a4079&quot;}" data-component-name="MentionToDOM"></span> </p><p><a href="https://blog.levelupcoding.com/p/luc-53-embracing-simplicity-look-stateless-design">Embracing Simplicity: A Look Into Stateless Design</a> - by Nikki Siapno</p><p><a href="https://tidyfirst.substack.com/p/why-accelerate-deployment">Why Accelerate Deployment?</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Kent Beck&quot;,&quot;id&quot;:24333739,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F000da410-0ed6-4a25-80b1-6a46e964ae0b_242x242.jpeg&quot;,&quot;uuid&quot;:&quot;a05f6dee-15a8-496a-b78d-fd787eecedbe&quot;}" data-component-name="MentionToDOM"></span> </p><div><hr></div><p>If you liked this post, share it with your friends and colleagues.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/p/no-branching-in-your-tests?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&amp;token=eyJ1c2VyX2lkIjoxMzg5MjgzMTQsInBvc3RfaWQiOjE0MjkyNDYzMSwiaWF0IjoxNzE1NTY5ODUwLCJleHAiOjE3MTgxNjE4NTAsImlzcyI6InB1Yi0xNTU4NjUyIiwic3ViIjoicG9zdC1yZWFjdGlvbiJ9.hhzf3slUwuKIaxQampm5JaXCmPLQ2QmqXcRb53nW2J8&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.thesunshinelayer.com/p/no-branching-in-your-tests?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&amp;token=eyJ1c2VyX2lkIjoxMzg5MjgzMTQsInBvc3RfaWQiOjE0MjkyNDYzMSwiaWF0IjoxNzE1NTY5ODUwLCJleHAiOjE3MTgxNjE4NTAsImlzcyI6InB1Yi0xNTU4NjUyIiwic3ViIjoicG9zdC1yZWFjdGlvbiJ9.hhzf3slUwuKIaxQampm5JaXCmPLQ2QmqXcRb53nW2J8"><span>Share</span></a></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Sunshine Layer! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[The social lives of unit tests]]></title><description><![CDATA[We often think about ourselves as social creatures. In software development, unit tests have social lives of their own.]]></description><link>https://www.thesunshinelayer.com/p/the-social-lives-of-unit-tests</link><guid isPermaLink="false">https://www.thesunshinelayer.com/p/the-social-lives-of-unit-tests</guid><dc:creator><![CDATA[Elena Sunshine]]></dc:creator><pubDate>Mon, 13 May 2024 05:01:31 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/82c81966-ebd8-46bd-a9a0-6f77bfa208b2_4200x3000.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The overarching goal of unit testing is to provide a reliable safety net that allows us, the developers, to modify and enhance software without fear of breaking existing functionality. This safety net is crucial, giving us the confidence to refactor code quickly and prevent our codebase from devolving into the dreaded <em>&#8220;ball of mud&#8221;</em>. Ultimately, every developer seeks the agility to change code swiftly and confidently, relying on tests to catch any lapses in logic or unforeseen side effects.</p><p>Yet, unit testing, pivotal in software development, is fraught with misconceptions that can dilute its effectiveness. A major point of contention is the definition of a "unit", leading to <a href="https://www.thesunshinelayer.com/p/detroit-vs-london-schools-of-unit">two distinct approaches to testing</a>, each profoundly shaping our methods and focus areas.</p><p>My favorite definition of a unit test comes from Vladimir Khorikov, and it&#8217;s a refinement of Kent Beck&#8217;s <a href="https://medium.com/@kentbeck_7670/test-desiderata-94150638a4b3">attributes of unit tests</a>. In his book <em><strong>"Unit Testing Principles, Practices, and Patterns"</strong></em>, Khorikov provides a concise breakdown for what unit tests should aim to achieve:</p><div class="pullquote"><p>a unit test (1) verifies a unit of software, (2) in isolation and (3) quickly.</p></div><p>While the third point is straightforward, as everyone wants fast feedback loop from running the test suite, the first two warrant further discussion.</p><h2>1. What&#8217;s a unit?</h2><p>Jay Fields, who <a href="https://leanpub.com/wewut">coined</a> "solitary" and "sociable" unit testing, highlights that sociable tests aim to check broader behaviors, offering a stark contrast to the solitary tests that focus on smaller, isolated chunks of behavior.</p><p>The solitary approach, frequently identified with the <strong>London School</strong> of testing, views <strong>a unit as </strong><em><strong>a single class or method</strong></em>, isolating it from external collaborators through the use of mocks. This method, while streamlining initial testing phases, tends to complicate maintenance as dependencies and system complexity grow.</p><p><em><strong>Solitary unit tests focus on smaller behaviors</strong></em> &#8212; specific computations or orchestration of collaborators &#8212; using test doubles to isolate each unit and ensuring that mocked interactions adhere to predefined contracts.</p><p>However, this perspective can be restrictive and misleading, as it focuses attention narrowly on isolated functions rather than on the overall behavior of the system.</p><p>Contrastingly, the sociable approach, often aligned with the <strong>Detroit School</strong> of testing, defines <strong>a unit as </strong><em><strong>a unit of behavior</strong></em> that encompasses interactions with its dependencies, unless external dependencies such as I/O operations demand isolation for efficiency.</p><p><em><strong>Sociable unit tests embrace the real interactions between components</strong></em>, ensuring that the system behaves as expected in a more integrated environment.</p><p>This brings us to the second point.</p><h2><strong>What do we isolate?</strong></h2><p>The natural answer would be to isolate the unit under test.</p><p><em><strong>If a unit is a class or a method, we want to test this unit in isolation from all external factors that might impact it.</strong></em></p><p><em><strong>All</strong> dependencies of that class</em> should be <em>replaced with test doubles</em> (like mocks) in tests (except for immutable dependencies).</p><p>By doing this we are making sure that failures are localized to the unit itself rather than being influenced by external factors or the behavior of dependencies.</p><p>So&#8230; that means we will mock out any dependencies of that class away.</p><p>Our test landscape would then look like this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nfGa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0aac517-c895-4c93-b97f-072d5356b993_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nfGa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0aac517-c895-4c93-b97f-072d5356b993_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!nfGa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0aac517-c895-4c93-b97f-072d5356b993_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!nfGa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0aac517-c895-4c93-b97f-072d5356b993_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!nfGa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0aac517-c895-4c93-b97f-072d5356b993_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nfGa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0aac517-c895-4c93-b97f-072d5356b993_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a0aac517-c895-4c93-b97f-072d5356b993_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1325205,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nfGa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0aac517-c895-4c93-b97f-072d5356b993_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!nfGa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0aac517-c895-4c93-b97f-072d5356b993_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!nfGa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0aac517-c895-4c93-b97f-072d5356b993_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!nfGa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0aac517-c895-4c93-b97f-072d5356b993_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><h2>What&#8217;s wrong with solitary unit testing?</h2><p>A common complaint with this approach is that any modification in the codebase necessitates changes in the tests.</p><p>By focusing the unit on a specific method or class you automatically create a tight coupling between the tests and the implementation, rather than the behavior. This often entails extensive use of mocks to simulate interactions between the class under test and its external dependencies.</p><p>The core problem here is in fact precisely this: this kind of tests are heavily mocked. Mock-based tests are rigid. This coupling can manifest in tests that verify whether specific methods were called with particular arguments, rather than focusing on the outcomes those interactions should achieve. Any deviation from that implementation, regardless whether just a mere organizational change, will trigger some tests to fail.</p><p>Furthermore, by isolating each component and replacing dependencies with mocks, developers may inadvertently lock themselves into a particular design too early. Because this approach demands a deep understanding of the domain model upfront - which is not always the case -, thus often leading to premature design decisions.</p><p>Over-reliance on mocks and substitutes leads to brittle tests that are highly sensitive to changes in the implementation of dependencies, spiraling into a maintenance burden, as changes in the system necessitate widespread updates to the accompanying mocks.</p><p>Not only does this hamper the agility of the development process, but also contradicts the core purpose of unit tests &#8212; to document and make sure the code has the expected behavior.</p><p>No, the core purpose of tests is not to mirror the code structure. The core promise of tests is to help us, to make refactoring safe and easy to do.</p><p>Moreover, the argument that tests become stale over time typically reflects a misunderstanding of unit testing's role. If tests are designed to verify behavior, they evolve only when these behaviors change, thereby serving as a living documentation of system expectations.</p><h3><strong>The Problem with Deep Domain Testing</strong></h3><p>When tests drill too deeply into the domain, instead of focusing on the API or the service's external interfaces, developers end up with an inflated test suite where many tests offer little to no additional coverage. These overly detailed tests often duplicate the scenarios already covered by broader tests, adding maintenance overhead without any of the corresponding benefits. Moreover, when a new class is extracted from an existing behavior, the necessity to create additional tests and modify existing ones can dissuade developers from making beneficial refactorings.</p><p></p><h2>What should trigger a new unit test?</h2><p>Spoiler alert: it&#8217;s not adding a new class.</p><p>What should <strong>trigger</strong> <strong>the need for writing a unit test is implementing a requirement. </strong>This means the <em>unit</em> is a <strong>UNIT OF BEHAVIOR</strong>. It's about <strong>fulfilling a functional need,</strong> not just verifying implementation details. This functional need is what should drive test creation, because it <strong>reflects what the software is expected</strong> to do.</p><p>In contrast, writing a test simply to check if a method <code>CalculateSum</code>, correctly adds up two numbers, focuses too much on implementation details. Such details, albeit important, should not dictate the testing strategy.</p><p>Instead, testing should be based on higher-level objectives or user needs.</p><p>This is where your tests should be targeted, ensuring they are relevant and directly tied to the requirements of the software.</p><p></p><h2>How do we implement sociable unit testing?</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3PrD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e7decc9-0eb8-4833-9875-78d9d4ffbb07_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3PrD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e7decc9-0eb8-4833-9875-78d9d4ffbb07_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!3PrD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e7decc9-0eb8-4833-9875-78d9d4ffbb07_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!3PrD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e7decc9-0eb8-4833-9875-78d9d4ffbb07_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!3PrD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e7decc9-0eb8-4833-9875-78d9d4ffbb07_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3PrD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e7decc9-0eb8-4833-9875-78d9d4ffbb07_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4e7decc9-0eb8-4833-9875-78d9d4ffbb07_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:545963,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3PrD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e7decc9-0eb8-4833-9875-78d9d4ffbb07_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!3PrD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e7decc9-0eb8-4833-9875-78d9d4ffbb07_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!3PrD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e7decc9-0eb8-4833-9875-78d9d4ffbb07_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!3PrD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e7decc9-0eb8-4833-9875-78d9d4ffbb07_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Focus on the public exports of your module, your facade. This preserves module encapsulation, crucial for maintaining flexibility.</p><p>Don&#8217;t focus on testing internals. These are implementation details.</p><p>Now, I know there&#8217;s a common practice to make internals visible to test projects. In C# we have the <em><strong>InternalsVisibleTo</strong></em> attribute. Refrain from using it, if you want to maintain the encapsulation of your module. It&#8217;s this encapsulation what actually preserves the system&#8217;s flexibility.</p><p>There&#8217;s one exception to this rule, and that&#8217;s when touching legacy code. There it&#8217;s perfectly fine to go ahead and break the encapsulation, as it is more valuable for that code to get under tests than to preserve its encapsulation. For new software, don&#8217;t use <em><strong>InternalsVisibleTo</strong></em>. This is what tweaks your development speed for the better in the long run.</p><p>Again, when we talk about sociable unit testing, the system under test is not just a class. The system under test are the exports of a module &#8212; its facade. This is your Domain in DDD that you&#8217;re testing. I&#8217;m not going to dive too much into this, as it&#8217;s a whole topic on its own, but simply think in terms of hexagonal architecture.</p><p>Allow your tests to be sociable. Allow them to communicate with real dependencies. The unit of isolation here is the test itself.</p><p></p><p>Circling back to Vladimir Khorikov&#8217;s three critical attributes of a unit test:</p><ol><li><p><strong>Unit of Software</strong>: This refers to the smallest piece of software that can be isolated for testing, which exhibits specific, <em>meaningful</em> behavior. This unit is not necessarily limited to a single method or class, but can involve any functional aspect significant from a business perspective.</p></li><li><p><strong>Isolation</strong>: This attribute emphasizes testing the unit in a controlled environment where dependencies are either simulated or managed to ensure the focus remains on the unit itself, rather than on external interactions.</p></li><li><p><strong>Quick Execution</strong>: The ability of a test to run swiftly complements the agile development process, enabling developers to receive immediate feedback and continuously refine the system with minimal disruption.</p></li></ol><h2>Code example</h2><p>Let&#8217;s consider the domain of a <code>Human Resources Management System</code> (HRMS). This system is responsible, among others, for managing employee records and payroll processes. We'll focus on a domain model that involves the interaction between <strong>Employee&#8217;s payroll calculations</strong>, considering factors like overtime payments.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tBRy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44972423-d054-4280-b429-1a2bffc2eaba_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tBRy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44972423-d054-4280-b429-1a2bffc2eaba_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!tBRy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44972423-d054-4280-b429-1a2bffc2eaba_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!tBRy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44972423-d054-4280-b429-1a2bffc2eaba_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!tBRy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44972423-d054-4280-b429-1a2bffc2eaba_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tBRy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44972423-d054-4280-b429-1a2bffc2eaba_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/44972423-d054-4280-b429-1a2bffc2eaba_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:172420,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tBRy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44972423-d054-4280-b429-1a2bffc2eaba_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!tBRy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44972423-d054-4280-b429-1a2bffc2eaba_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!tBRy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44972423-d054-4280-b429-1a2bffc2eaba_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!tBRy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44972423-d054-4280-b429-1a2bffc2eaba_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The Payroll business logic is implemented by the StandardPayRatePolicy, as follows: if it&#8217;s standard time, then multiply number of hours by standard rate, otherwise, if overtime, multiply the rate by 1.5 first, and then multiply by the number of hours worked.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uyXA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbe13c34-e482-46b2-8ab9-be1c2ee724a9_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uyXA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbe13c34-e482-46b2-8ab9-be1c2ee724a9_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!uyXA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbe13c34-e482-46b2-8ab9-be1c2ee724a9_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!uyXA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbe13c34-e482-46b2-8ab9-be1c2ee724a9_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!uyXA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbe13c34-e482-46b2-8ab9-be1c2ee724a9_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uyXA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbe13c34-e482-46b2-8ab9-be1c2ee724a9_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dbe13c34-e482-46b2-8ab9-be1c2ee724a9_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:245540,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uyXA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbe13c34-e482-46b2-8ab9-be1c2ee724a9_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!uyXA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbe13c34-e482-46b2-8ab9-be1c2ee724a9_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!uyXA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbe13c34-e482-46b2-8ab9-be1c2ee724a9_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!uyXA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbe13c34-e482-46b2-8ab9-be1c2ee724a9_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In solitary unit testing, this would start with creating a test class for the Employee class. And since we want to isolate the unit under test, we will mock every dependency of that class - <code>IPayRatePolicy </code>in our case.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lD4g!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70263978-ab07-4175-8612-3ab2e3da0350_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lD4g!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70263978-ab07-4175-8612-3ab2e3da0350_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!lD4g!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70263978-ab07-4175-8612-3ab2e3da0350_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!lD4g!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70263978-ab07-4175-8612-3ab2e3da0350_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!lD4g!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70263978-ab07-4175-8612-3ab2e3da0350_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lD4g!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70263978-ab07-4175-8612-3ab2e3da0350_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/70263978-ab07-4175-8612-3ab2e3da0350_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:370097,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lD4g!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70263978-ab07-4175-8612-3ab2e3da0350_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!lD4g!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70263978-ab07-4175-8612-3ab2e3da0350_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!lD4g!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70263978-ab07-4175-8612-3ab2e3da0350_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!lD4g!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70263978-ab07-4175-8612-3ab2e3da0350_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This ends up with twisted tested behavior. It&#8217;s a perfect depiction of how tests cluttered with mocks tend to focus too much on the interaction with mocks rather than the real outcomes, making it challenging to discern what is actually being tested and why tests fail when implementation details change.</p><p>Furthermore, frequent changes in the codebase will probably lead to outdated mocks, making it difficult to ensure that tests still reflect the true behavior of the system.</p><p>But what about <code>PayRatePolicy</code>?<br>For it, we would end up creating a new test class, which indeed would be focused on the behavior itself.</p><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bpRM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fafeda903-7cc7-49b1-8bfa-286235333389_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bpRM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fafeda903-7cc7-49b1-8bfa-286235333389_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!bpRM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fafeda903-7cc7-49b1-8bfa-286235333389_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!bpRM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fafeda903-7cc7-49b1-8bfa-286235333389_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!bpRM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fafeda903-7cc7-49b1-8bfa-286235333389_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bpRM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fafeda903-7cc7-49b1-8bfa-286235333389_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/afeda903-7cc7-49b1-8bfa-286235333389_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:423635,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bpRM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fafeda903-7cc7-49b1-8bfa-286235333389_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!bpRM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fafeda903-7cc7-49b1-8bfa-286235333389_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!bpRM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fafeda903-7cc7-49b1-8bfa-286235333389_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!bpRM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fafeda903-7cc7-49b1-8bfa-286235333389_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>But what happens when we realize some of that behavior needs to be extracted away to keep our code base clean?</p><p>You guessed it. Tests will start failing and new tests will need to be written to accommodate the new implementation details. But did the business logic change? Not one bit.</p><h3><strong>Let&#8217;s now turn to sociable unit tests.</strong></h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dhio!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa514c7c9-ab58-434f-bd23-1374639c2914_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dhio!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa514c7c9-ab58-434f-bd23-1374639c2914_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!dhio!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa514c7c9-ab58-434f-bd23-1374639c2914_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!dhio!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa514c7c9-ab58-434f-bd23-1374639c2914_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!dhio!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa514c7c9-ab58-434f-bd23-1374639c2914_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dhio!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa514c7c9-ab58-434f-bd23-1374639c2914_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a514c7c9-ab58-434f-bd23-1374639c2914_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:454153,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!dhio!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa514c7c9-ab58-434f-bd23-1374639c2914_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!dhio!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa514c7c9-ab58-434f-bd23-1374639c2914_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!dhio!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa514c7c9-ab58-434f-bd23-1374639c2914_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!dhio!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa514c7c9-ab58-434f-bd23-1374639c2914_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>We end up with less tests overall, which are laser focused on our business logic. Regardless of how many tweaks and splits into separate classes we do, as long as the behavior stays the same, the tests won&#8217;t fail. Our trust in the test suite increases, and our overall development speed together with it.</p><h2>General guidelines for writing sociable tests</h2><h3><strong>Utilize specific domain entities</strong></h3><p>Start by using specific entities that are central to your domain. This helps ground your tests in the reality of your application's environment. You can then modify these entities according to the specific requirements of each test. It ensures that the tests are relevant and provide valuable insights into how the system behaves under different conditions.</p><h3><strong>Make asserts meaningful</strong></h3><p>In sociable unit testing, asserts are not just checks; they serve as documentation for the business logic they test. Each assert should clearly communicate what it&#8217;s testing and why that behavior is important. This makes tests easier to understand and maintain, and it turns the test suite into a form of documentation that can be useful for both developers and non-technical stakeholders.</p><h3><strong>Focus on the Behavior, not the Class</strong></h3><p>Shift your focus from testing specific classes to testing behaviors across classes. This change in perspective helps ensure that the tests assess the system&#8217;s functionality and user-facing behaviors rather than just the internal logic of its components. By focusing on behaviors, sociable unit tests can provide more meaningful assurances about the system's readiness for production.</p><h3><strong>Efficient execution strategies</strong></h3><p>Sociable unit tests can be more resource-intensive than solitary tests, primarily because they involve more components and require more setup. To manage this, consider not running all sociable unit tests all the time, especially during the early stages of development. Alternatively, you can run all the tests but do so in parallel to reduce the time impact. Modern CI/CD tools and test frameworks offer capabilities to run tests in parallel, leveraging cloud resources and multi-threading to handle the increased load efficiently.</p><h2>Concerns and challenges</h2><h3><strong>Breaking the testing pyramid</strong></h3><p>There is a common misconception that sociable unit tests blur the lines with integration tests, potentially breaking the traditional testing pyramid.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5DLI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb6f8ee7-47f2-4914-a6b4-c7d62de14134_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5DLI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb6f8ee7-47f2-4914-a6b4-c7d62de14134_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!5DLI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb6f8ee7-47f2-4914-a6b4-c7d62de14134_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!5DLI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb6f8ee7-47f2-4914-a6b4-c7d62de14134_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!5DLI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb6f8ee7-47f2-4914-a6b4-c7d62de14134_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5DLI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb6f8ee7-47f2-4914-a6b4-c7d62de14134_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/db6f8ee7-47f2-4914-a6b4-c7d62de14134_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:154217,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5DLI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb6f8ee7-47f2-4914-a6b4-c7d62de14134_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!5DLI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb6f8ee7-47f2-4914-a6b4-c7d62de14134_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!5DLI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb6f8ee7-47f2-4914-a6b4-c7d62de14134_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!5DLI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb6f8ee7-47f2-4914-a6b4-c7d62de14134_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>However, that&#8217;s not the case, as each type of tests serves distinct purposes:</p><ul><li><p><strong>Unit Tests</strong></p><p>While they involve multiple classes, the focus of sociable unit tests is on the logic within a specific module or component, regardless of how it is organized. They are interested in the<strong> smallest units of behavior, </strong>which in this context, are the public exports of a module&#8212;essentially the functionalities exposed to the users or other modules. The key is what happens in the facade as a result of that logic, not just that the integration points work. We are testing internal logic (Class B, C, Z) through that facade (Class A).</p></li><li><p><strong>Integration Tests</strong></p><p>These tests are designed to verify the collaboration between such modules and ensure that various parts of the system work together as expected.</p></li><li><p><strong>End to End Tests</strong></p><p>They are responsible to make sure the whole system communicates well.</p></li></ul><h3><strong>Addressing Architectural Challenges</strong></h3><p>Sometimes, creating a reusable setup for sociable unit tests proves too challenging, indicating a potential issue with the architecture itself. Difficulty in configuring tests for certain interactions might suggest that the components in question do not belong in the same context or domain. This difficulty can serve as a valuable indicator that it may be necessary to reevaluate and potentially redefine the architectural or domain boundaries. Such a reevaluation can lead to a more intuitive and coherent system architecture that better supports both development and testing.</p><h3><strong>The Role of Mocks and Test Doubles</strong></h3><p>Despite the emphasis on using real dependencies, the use of mocks and test doubles cannot be completely eliminated, especially when dealing with external services where non-determinism is a factor. Even staunch <a href="https://martinfowler.com/bliki/UnitTest.html">advocates of classical testing</a> acknowledge their value in removing non-determinism, particularly in awkward collaborations.</p><p>Favor using fakes&#8212;simplified implementations of complex interfaces&#8212;over mocks. While mocks are useful for isolating behavior, they can lead to tests that are too closely tied to the implementation details of a component. Fakes allow for testing the interaction with dependencies in a way that is less brittle and more representative of actual interactions within the application.</p><h3><strong>When to Use Test Doubles</strong></h3><p>The decision to use test doubles should consider:</p><ul><li><p><strong>Complexity of the SUT</strong>: In highly complex systems, using test doubles can help manage this complexity by simplifying the test environment. However, for systems where interactions are crucial to functionality, real dependencies might be necessary.</p></li><li><p><strong>Test Maintenance Effort</strong>: Test doubles can reduce initial setup time but may increase maintenance effort if the system evolves and the interfaces between components change.</p></li></ul><h3><strong>Efficient Execution Strategies</strong></h3><p>Given the often extensive nature of sociable unit tests, it's impractical to run all tests frequently. Typically, only those tests that pertain to the code currently under development are run regularly. This targeted approach, which I refer to as the "compile suite," is essential for maintaining the balance between depth of testing and runtime</p><h3><strong>Advantages and Challenges of Sociable Unit Tests</strong></h3><p><strong>Pros:</strong></p><ul><li><p><strong>Validate Refactoring</strong>: One of the significant advantages of sociable unit tests is their ability to validate the system's behavior after refactoring. Because these tests are less tied to implementation details, they allow for substantial code modifications without the need to rewrite the tests, provided the external behavior remains consistent.</p></li><li><p><strong>Simplified Maintenance</strong>:</p><p>By reducing the reliance on mocks and stubs, there is less overhead in configuring and updating tests. This simplification leads to easier maintenance since changes in the codebase do not necessitate widespread updates across numerous mock setups.</p></li><li><p><strong>Behavioral Coverage</strong>: They are excellent for capturing emergent behaviors in complex systems that might be missed by more granular tests. These tests validate the integration of components, ensuring that the system works as expected in a setup that closely mimics the production environment.</p></li><li><p><strong>Reinforce Better Modularization</strong>: By testing how well components interact with their real dependencies, sociable unit tests encourage better system design and modularization.</p></li><li><p><strong>Indicate Boundaries</strong>: These tests help define and reinforce the boundaries of a component's responsibilities by clearly outlining how it should interact with other parts of the system.</p></li><li><p><strong>Enhanced Reliability</strong>:</p><p>Using actual code interactions rather than relying on potentially flawed mock contracts increases the reliability of tests. Real interactions expose the system to more variable conditions and edge cases, improving the robustness of the software.</p></li></ul><p><strong>Cons:</strong></p><ul><li><p><strong>Verbose/Complex Setup</strong>: Setting up sociable unit tests can be more complex and time-consuming than solitary tests because they often involve configuring real system dependencies.</p></li><li><p><strong>(Can be) Slower</strong>: Because they interact with real components rather than mocks, sociable unit tests may execute more slowly, which could impact the speed of the development cycle. Whenever that really is the case, use test doubles.</p></li></ul><h2><strong>Conclusion</strong></h2><p>By fostering tests that mirror real-world use rather than just code structure, sociable unit tests enhance not just the robustness but also the relevance of our testing practices. They prepare software not just to work, but to work in the way users truly need. This not only stabilizes the foundation of our applications but also streamlines the development process, making our software more adaptable and resilient to changes.</p><div><hr></div><div><hr></div><h1>Pay it forward</h1><p>Here are this edition&#8217;s knowledge nuggets that made me pause and think:</p><p><a href="https://newsletter.francofernando.com/p/server-sent-event?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">Server-Sent Event</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Franco Fernando&quot;,&quot;id&quot;:47169986,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/58a41b86-1e25-4bd0-a448-138d50731db4_800x800.png&quot;,&quot;uuid&quot;:&quot;af2f3586-bb02-4157-81b1-0863bbc13911&quot;}" data-component-name="MentionToDOM"></span> </p><p><a href="https://newsletter.systemdesigncodex.com/p/stateless-architecture?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">Stateless Architecture - What's the Deal?</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Saurabh Dashora&quot;,&quot;id&quot;:97484183,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9626145f-2837-4635-becf-04a372de29e2_607x607.jpeg&quot;,&quot;uuid&quot;:&quot;8523a13e-34c6-4603-b2df-1bb1a2484035&quot;}" data-component-name="MentionToDOM"></span> </p><p><a href="https://craftbettersoftware.com/p/why-you-need-tdd?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">Why you need TDD</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Daniel Moka&quot;,&quot;id&quot;:5505375,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b31d65c1-d5b9-40e6-8350-f82cbd17233e_400x400.jpeg&quot;,&quot;uuid&quot;:&quot;be8b4e55-52ef-438a-a18b-e32ef635fa24&quot;}" data-component-name="MentionToDOM"></span> </p><p><a href="https://medium.com/@maciej.pocwierz/how-an-empty-s3-bucket-can-make-your-aws-bill-explode-934a383cb8b1">How an empty S3 bucket can make your AWS bill explode</a><a href="https://substack.com/home/post/p-142395646?r=2appru&amp;utm_campaign=post&amp;utm_medium=web"> </a>- by Maciej Pocwierz</p><div><hr></div><p>If you liked this post, share it with your friends and colleagues.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/p/no-branching-in-your-tests?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&amp;token=eyJ1c2VyX2lkIjoxMzg5MjgzMTQsInBvc3RfaWQiOjE0MjkyNDYzMSwiaWF0IjoxNzE1NTY5ODUwLCJleHAiOjE3MTgxNjE4NTAsImlzcyI6InB1Yi0xNTU4NjUyIiwic3ViIjoicG9zdC1yZWFjdGlvbiJ9.hhzf3slUwuKIaxQampm5JaXCmPLQ2QmqXcRb53nW2J8&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.thesunshinelayer.com/p/no-branching-in-your-tests?utm_source=substack&amp;utm_medium=email&amp;utm_content=share&amp;action=share&amp;token=eyJ1c2VyX2lkIjoxMzg5MjgzMTQsInBvc3RfaWQiOjE0MjkyNDYzMSwiaWF0IjoxNzE1NTY5ODUwLCJleHAiOjE3MTgxNjE4NTAsImlzcyI6InB1Yi0xNTU4NjUyIiwic3ViIjoicG9zdC1yZWFjdGlvbiJ9.hhzf3slUwuKIaxQampm5JaXCmPLQ2QmqXcRb53nW2J8"><span>Share</span></a></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Sunshine Layer! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[No branching in your tests]]></title><description><![CDATA[Why eliminating ifs in your tests leads to more predictable outcomes and strategies to keep your codebase decluttered.]]></description><link>https://www.thesunshinelayer.com/p/no-branching-in-your-tests</link><guid isPermaLink="false">https://www.thesunshinelayer.com/p/no-branching-in-your-tests</guid><dc:creator><![CDATA[Elena Sunshine]]></dc:creator><pubDate>Wed, 03 Apr 2024 04:31:10 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/9d6f089a-5c95-4332-b077-d581c5da2298_4200x3000.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When it comes to software development, simplicity is king. This applies even more so when it comes to testing, whether it's unit or integration tests. But in the race of efficiency, we may stumble upon a fake optimization: using <code>if</code><em> statements</em> in tests.</p><p>Let's understand why they're problematic and how to avoid them.</p><h1><strong>The Problem</strong></h1><p>We have a behavior we want to test, and there&#8217;s a complex setup to get to it. There might be similar edge cases that we want to cover, there might be some external dependency. The problem happens when we try to be smart and tackle uncertainty when writing a test, using conditionals.</p><p>Don&#8217;t be fooled to think that this is efficient. It&#8217;s not.</p><p><em><strong>Don't overcomplicate things</strong></em>. The moment you introduce an <code>if</code> into a test, you're essentially inviting complexity. It's a sign that the test is trying to cover too much ground.</p><p>It's trading it all for a <em><strong>lack of clarity and a loss in focus</strong></em>. That&#8217;s not efficiency. Optimal tests maintain a laser-focused approach, examining one specific aspect or behavior at a time. Having such <code>if</code>s blurs this focus, trying to encompass multiple scenarios in one go.</p><p>Not to mention, tests with conditional logic are much harder to maintain. They become riddled with paths that make understanding and updating them more difficult.</p><p>Yet, there is a deeper layer to this discussion, centering on the nature of the functions and methods we test. The ease or difficulty of testing a piece of code often boils down to its purity or impurity.</p><h1>Pure and impure methods</h1><p>Methods that are deterministic and side-effect-free, known in functional programming as <em>pure functions</em>, present a testing ideal.</p><p>Pure functions, by definition, always return the same output for the same input and <strong>have no side effects</strong>&#8212;meaning they don't alter any state outside themselves or rely on an external state.</p><p>This attribute not only aids in straightforward testing but also in enhancing the functions' reusability and integration into larger systems without complicating state management or dependencies.</p><p>On the other hand, impure functions, which depend on external states or cause side effects, complicate testing. Such functions can make the codebase harder to maintain by introducing dependencies and unpredictability.</p><p>While it's unrealistic to completely eliminate impure functions, their impact can be minimized by isolating them within the application.</p><p>This involves:</p><ul><li><p>Separating pure and impure functions</p></li><li><p>Reducing the reliance on impure interactions</p></li><li><p>Facilitating dependency injection or fakes for testing.</p></li></ul><h1><strong>The Ideal approach</strong></h1><h3>Aim for single responsibility tests.</h3><p>Each test should validate <em>one and only one condition or behavior</em>. If you find yourself needing an <em><strong>if</strong></em>, it's likely that the test can be broken down into multiple, more focused tests or you need to break down your dependencies.</p><h3>Avoid branching at all costs.</h3><p>A test should be a straight path, not a branching tree. Instead of one test with an <code>if</code> statement, create multiple scenario-specific tests. Each tailored to a specific scenario or condition. It should follow a clear <strong>Arrange-Act-Assert (AAA) pattern</strong> without deviating into different scenarios.</p><p>Speaking of <em><strong>AAA</strong></em>, I personally find no use for <code>// Arrange</code>, <code>// Act</code>, and <code>// Assert</code> comments in code, as long as you can separate the sections by empty lines. </p><p>Besides, by clearly naming the system under test &#8220;sut&#8221;, when calling it, and storing the result in a &#8220;result&#8221; variable, it&#8217;s clear what&#8217;s being tested <em>(act)</em> and that everything before represented the setup <em>(arrange)</em>.</p><blockquote><p><code>var result = sut.PerformTask();</code></p></blockquote><p>I won&#8217;t dive into the assertion bit, as it is self explanatory.</p><h3>Target explicitness.</h3><p>Tests should explicitly state what they're checking. When you read a test, its purpose and scenario should be immediately clear without needing to deep dive and decipher the logic.</p><p>That&#8217;s why I&#8217;m not necessarily keen on having strict test naming conventions such as <code>[Given]_[When]_[Then]</code> or <code>[MethodUnderTestName]_[Scenario]_[Result]</code>.</p><p>Such conventions makes reasoning about tests difficult and often require you to look further into it in order to understand what&#8217;s actually being tested.</p><p>On top of that, especially the latter version, encourages you to focus on the implementation details and on isolating the method, instead of testing a <strong>behavior</strong>. I&#8217;ve already covered why you should strive to test units of behavior <a href="https://www.thesunshinelayer.com/p/detroit-vs-london-schools-of-unit">here</a>.</p><p>I prefer a more natural, English-style phrasing, to depict the business case the test fulfils, as it makes reasoning about what&#8217;s being tested much easier.</p><p>For instance, instead of a generic name, I favor using something like <code>user_login_with_valid_credentials_authenticates_successfully</code> or <code>user_login_with_invalid_credentials_fails_authentication</code>.</p><h3>Refactoring tests.</h3><p>Regularly review and refactor your tests. As your codebase changes, ensure your tests remain relevant, clear, and focused. All code is a liability. Test code is still code, hence no stranger to this rule.</p><h1>Diving into unit testing with xUnit</h1><p>Let&#8217;s dive into some concrete code examples. For the purpose of this, I&#8217;m using C# with xUnit as my favorite playground.</p><p>As mentioned, we <strong>don&#8217;t </strong><em><strong>optimize </strong></em><strong>the code by crafting one test with multiple branching to cover multiple scenarios</strong>, but <strong>we craft specific tests for each case</strong>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tYGI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbf4115-77e0-45f4-a0dc-702801c8b9da_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tYGI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbf4115-77e0-45f4-a0dc-702801c8b9da_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!tYGI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbf4115-77e0-45f4-a0dc-702801c8b9da_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!tYGI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbf4115-77e0-45f4-a0dc-702801c8b9da_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!tYGI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbf4115-77e0-45f4-a0dc-702801c8b9da_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tYGI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbf4115-77e0-45f4-a0dc-702801c8b9da_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dbbf4115-77e0-45f4-a0dc-702801c8b9da_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:673055,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tYGI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbf4115-77e0-45f4-a0dc-702801c8b9da_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!tYGI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbf4115-77e0-45f4-a0dc-702801c8b9da_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!tYGI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbf4115-77e0-45f4-a0dc-702801c8b9da_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!tYGI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbf4115-77e0-45f4-a0dc-702801c8b9da_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>What if there are multiple edge cases to cover, all with a rather similar setup? That&#8217;s where <code>[Theory]</code> attribute comes to save the day.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZikI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0365bbde-a090-47b6-a2b4-730d51c48e00_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZikI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0365bbde-a090-47b6-a2b4-730d51c48e00_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!ZikI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0365bbde-a090-47b6-a2b4-730d51c48e00_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!ZikI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0365bbde-a090-47b6-a2b4-730d51c48e00_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!ZikI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0365bbde-a090-47b6-a2b4-730d51c48e00_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZikI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0365bbde-a090-47b6-a2b4-730d51c48e00_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0365bbde-a090-47b6-a2b4-730d51c48e00_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:438082,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ZikI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0365bbde-a090-47b6-a2b4-730d51c48e00_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!ZikI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0365bbde-a090-47b6-a2b4-730d51c48e00_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!ZikI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0365bbde-a090-47b6-a2b4-730d51c48e00_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!ZikI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0365bbde-a090-47b6-a2b4-730d51c48e00_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Using xUnit's <code>[Theory]</code> attribute with <code>[InlineData]</code> allows for <strong>parameterized tests</strong>, covering multiple scenarios without resorting to conditional logic. Each data line represents a distinct, clear scenario, easy to pinpoint and debug. But the data is not so depictive, as it needs comments to make it clear. Let&#8217;s fix that.</p><h2><strong>Advanced Strategies for Complex Data</strong></h2><p>For such complex scenarios <code>[InlineData(...)]</code> reaches its limits. But xUnit offers two potent solutions: <code>[MemberData(...)]</code> and <code>[ClassData(...)]</code>.</p><h3><code>[MemberData(...)]</code></h3><p>The <code>[MemberData(...)]</code> attribute allows you to reference a static property, field, or method within the test class or another class that returns an <code>IEnumerable&lt;object[]&gt;</code>, where each <code>object[]</code> contains a set of parameters for the test method.</p><p>This approach is particularly useful when your test data is too complex for inline definitions or when you want to share test data among multiple test methods.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gokw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e6bd860-6191-42fa-b4ad-6d2eff9f5cc4_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gokw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e6bd860-6191-42fa-b4ad-6d2eff9f5cc4_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!gokw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e6bd860-6191-42fa-b4ad-6d2eff9f5cc4_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!gokw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e6bd860-6191-42fa-b4ad-6d2eff9f5cc4_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!gokw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e6bd860-6191-42fa-b4ad-6d2eff9f5cc4_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gokw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e6bd860-6191-42fa-b4ad-6d2eff9f5cc4_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3e6bd860-6191-42fa-b4ad-6d2eff9f5cc4_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:693775,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!gokw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e6bd860-6191-42fa-b4ad-6d2eff9f5cc4_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!gokw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e6bd860-6191-42fa-b4ad-6d2eff9f5cc4_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!gokw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e6bd860-6191-42fa-b4ad-6d2eff9f5cc4_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!gokw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e6bd860-6191-42fa-b4ad-6d2eff9f5cc4_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><code>[ClassData(...)]</code></h3><p>For scenarios where even <code>[MemberData(...)]</code> might not be enough&#8212;perhaps due to complex setup that you want reused across multiple test classes or simply because you need data encapsulation, <code>[ClassData(...)]</code> steps in.</p><p>The <code>[ClassData]</code> attribute specifies a class that implements <code>IEnumerable&lt;object[]&gt;</code> to provide the data for the test method. This class must have a parameterless constructor.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZczD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924e570a-4f9b-4894-8346-4033d03fe778_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZczD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924e570a-4f9b-4894-8346-4033d03fe778_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!ZczD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924e570a-4f9b-4894-8346-4033d03fe778_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!ZczD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924e570a-4f9b-4894-8346-4033d03fe778_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!ZczD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924e570a-4f9b-4894-8346-4033d03fe778_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZczD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924e570a-4f9b-4894-8346-4033d03fe778_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/924e570a-4f9b-4894-8346-4033d03fe778_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:851591,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ZczD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924e570a-4f9b-4894-8346-4033d03fe778_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!ZczD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924e570a-4f9b-4894-8346-4033d03fe778_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!ZczD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924e570a-4f9b-4894-8346-4033d03fe778_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!ZczD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924e570a-4f9b-4894-8346-4033d03fe778_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h1>Conclusion</h1><p>Remember, when writing code and even more so in testing, less is often more.</p><p>Avoid the temptation to create complex, conditional tests. Strive for simplicity, clarity, and focus.</p><p>By keeping <code>if</code> statements out of your tests and adhering to the principle of single responsibility, your tests become more reliable, understandable, and maintainable.</p><p></p><div><hr></div><h1>Pay it forward</h1><p>Here are this week&#8217;s knowledge nuggets that made me pause and think:</p><p><a href="https://newsletter.systemdesign.one/p/disney-architecture?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">How Disney+ Scaled to 11 Million Users on Launch Day</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Neo Kim&quot;,&quot;id&quot;:135589200,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c103940f-0d8b-47e7-9a33-013202e17bb8_389x389.jpeg&quot;,&quot;uuid&quot;:&quot;7b1ff07f-7447-45f5-8548-f291740b5d0e&quot;}" data-component-name="MentionToDOM"></span> </p><p><a href="https://open.substack.com/pub/jadecodes/p/startup-vs-big-tech-whats-the-difference?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">STARTUP VS BIG TECH: What's the difference?</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Jade Wilson&quot;,&quot;id&quot;:199051090,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f9fec516-b273-4d69-96b3-ccf80643a91e_698x698.jpeg&quot;,&quot;uuid&quot;:&quot;6c66001c-66ad-4534-9606-1c707877d89e&quot;}" data-component-name="MentionToDOM"></span> </p><p><a href="https://www.thecaringtechie.com/p/how-to-self-manage-even-if-you-have?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">How to Self-Manage Even if You Have a Manager</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Irina Stanescu&quot;,&quot;id&quot;:4332862,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7eea2778-f26d-4f4b-9529-93fe29c3fdce_422x368.png&quot;,&quot;uuid&quot;:&quot;3e500989-9ab2-48ed-af17-9ff4daa5ae23&quot;}" data-component-name="MentionToDOM"></span> </p><p><a href="https://open.substack.com/pub/strategictech/p/treat-your-career-as-a-startup?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">Treat your career as a startup</a><a href="https://substack.com/home/post/p-142395646?r=2appru&amp;utm_campaign=post&amp;utm_medium=web"> </a>- by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Bogdan Veliscu&quot;,&quot;id&quot;:115684107,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8794f76d-22a4-4475-b0d3-8af9c9cc21b3_800x800.png&quot;,&quot;uuid&quot;:&quot;f3928916-e887-4c68-9ffc-7228f3c6e9ef&quot;}" data-component-name="MentionToDOM"></span> </p><div><hr></div><p>If you liked this post, share it with your friends and colleagues.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/p/no-branching-in-your-tests?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thesunshinelayer.com/p/no-branching-in-your-tests?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Sunshine Layer! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[Your system's exceptions are a ticking time bomb]]></title><description><![CDATA[Why eliminating exceptions in favor of functional error handling is a game-changer for your system' stability.]]></description><link>https://www.thesunshinelayer.com/p/your-systems-exceptions-are-a-ticking</link><guid isPermaLink="false">https://www.thesunshinelayer.com/p/your-systems-exceptions-are-a-ticking</guid><dc:creator><![CDATA[Elena Sunshine]]></dc:creator><pubDate>Tue, 26 Mar 2024 06:01:28 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/276917f1-e478-4494-b7ab-8fb350cecd86_4200x3000.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Exceptions have long been the go-to mechanism for signaling and handling unusual circumstances within applications, across many languages.</p><p>But let&#8217;s set the record straight.</p><p>Just because they can be used to announce something went wrong, doesn&#8217;t mean they should be used and abused as general purpose for error handling.</p><p>Exceptions are, as their name suggests, <strong>exceptional</strong>. They serve <strong>exceptional</strong> circumstances &#8212; unpredictable events that fall outside the normal operation of a program.</p><p>Business rules violations and data validation are <strong>expected flows</strong>. They&#8217;re conditions and scenarios that developers can foresee and thus, should plan for. There isn&#8217;t anything &#8220;exceptional&#8221; to them. They're anticipated pathways that require <strong>explicit handling</strong> within your application's logic. Using exceptions in such cases fundamentally misunderstands their purpose.</p><p>If you&#8217;re throwing exceptions <em>expecting</em> its invoker to catch it, then you need to rethink your error handling strategy. Such indiscriminate use of exceptions, especially for routine error handling, obfuscates control flow, degrades performance, and will make your code harder to understand and maintain.</p><p>I&#8217;m not the only one saying it.</p><p>Wikipedia defines exceptions as</p><blockquote><p>anomalous or exceptional conditions requiring special processing &#8211; during the&nbsp;execution&nbsp;of a&nbsp;program. In general, an exception breaks the normal flow of execution and executes a pre-registered&nbsp;exception handler;</p></blockquote><p>On <a href="https://learn.microsoft.com/en-us/dotnet/standard/exceptions/best-practices-for-exceptions">Microsoft&#8217;s side</a>, the general advice is to thread carefully into exception territory:</p><blockquote><p>The C# language's exception handling features help you deal with any <em>unexpected or exceptional situations</em> that occur when a program is running.</p></blockquote><blockquote><p>For conditions that are likely to occur but might trigger an exception, consider handling them in a way that will avoid the exception.</p></blockquote><p></p><h4>Let&#8217;s have a closer look and understand the why behind the no-exception reasoning.</h4><h2>Performance costs</h2><p>It might be really tempting to create exceptions, throw them and think you&#8217;ll deal with them later. But throwing exceptions incurs a significant performance cost due to the underlying operations involved - think stack unwinding.</p><p>This overhead is particularly problematic in performance-sensitive areas of an application.</p><h2>Obscured logic and flow interruption</h2><p>When exceptions are used liberally, the control flow of an application becomes fragmented and less intuitive.</p><p>Exceptions are a form of non-local control, acting as glorified go-to calls that interrupt the execution flow. This fragmentation complicates the task of tracing through code when you want to understand how errors are handled, and ultimately leads to inconsistent error management practices.</p><p>To put it more bluntly, exceptions cause jumps from one known point in our application to whatever point, in whichever state, often in ways that are hard to reason about. That is <em>if</em> we define that catch point somewhere.</p><p>When thinking about the business context of your problem, you should create abstractions that help understanding the domain and flow. Don&#8217;t be fooled to think that by crafting <code>MyCustomException : Exception</code> you&#8217;re building that abstraction over your domain. Exceptions act like a uno card that&#8217;s gonna pull a reverse on you later on. You think you got rid of the problem, but in fact you just made it more complex.</p><h2>The False Security of exception handling</h2><p>Relying on exceptions for error handling gives a false sense of security. The very act of throwing an exception for known error conditions, such as a missing dependency, although necessary in some cases, should be the exception rather than the rule.</p><p>By all means, if you really need the application to crash because you cannot continue, do so.</p><p>Just keep in mind to ponder really well whether that&#8217;s really the case. Don&#8217;t make code more complex and harder to maintain just because it&#8217;s &#8220;easy&#8221;.</p><p>And no, having a application-wide catch-all is not a great idea either. What are you catching? What are you forecasting to handle and how?</p><h2>Deceiving nature of methods&#8217; signature</h2><p>In C# exceptions are hidden and make methods deceiving. When looking at the signature of a method, you&#8217;ll be easily tricked into expecting a certain return type. However, that signature is fooling you, by not giving you all the information.</p><p>There&#8217;s no proper way to know about the possible exceptions it might throw, except from the<em> xml documentation</em> a thoughtful author <strong>might&#8217;ve</strong> created (<em>if any</em>).</p><p>Let&#8217;s take the <code>FileStream</code> of Microsoft. We see there&#8217;s a bunch of exceptions presented as possible scenarios. But it makes for a horrible developer experience.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nGqX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F307d2880-b230-4d7b-8675-8b2aa70bdf29_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nGqX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F307d2880-b230-4d7b-8675-8b2aa70bdf29_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!nGqX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F307d2880-b230-4d7b-8675-8b2aa70bdf29_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!nGqX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F307d2880-b230-4d7b-8675-8b2aa70bdf29_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!nGqX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F307d2880-b230-4d7b-8675-8b2aa70bdf29_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nGqX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F307d2880-b230-4d7b-8675-8b2aa70bdf29_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/307d2880-b230-4d7b-8675-8b2aa70bdf29_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1044330,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nGqX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F307d2880-b230-4d7b-8675-8b2aa70bdf29_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!nGqX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F307d2880-b230-4d7b-8675-8b2aa70bdf29_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!nGqX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F307d2880-b230-4d7b-8675-8b2aa70bdf29_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!nGqX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F307d2880-b230-4d7b-8675-8b2aa70bdf29_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>You now have to wrap chunks of code in different try statements, interrupting the execution of your function.</p><p>Should you have to worry about all these cases as errors?</p><p>Couldn&#8217;t they have been depicted any other way?</p><p>And even if you do your due diligence and cover all cases, what if tomorrow they decide to throw on a different exception?</p><p>Here we&#8217;re talking Microsoft, which is quite gentle with developers. What if we talk external public packages? What if we talk cross-team packages? What if we talk inner-team?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!i8Rg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22ead42c-4d54-47ac-a539-1ef40800a3b4_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!i8Rg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22ead42c-4d54-47ac-a539-1ef40800a3b4_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!i8Rg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22ead42c-4d54-47ac-a539-1ef40800a3b4_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!i8Rg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22ead42c-4d54-47ac-a539-1ef40800a3b4_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!i8Rg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22ead42c-4d54-47ac-a539-1ef40800a3b4_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!i8Rg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22ead42c-4d54-47ac-a539-1ef40800a3b4_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/22ead42c-4d54-47ac-a539-1ef40800a3b4_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:277736,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!i8Rg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22ead42c-4d54-47ac-a539-1ef40800a3b4_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!i8Rg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22ead42c-4d54-47ac-a539-1ef40800a3b4_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!i8Rg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22ead42c-4d54-47ac-a539-1ef40800a3b4_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!i8Rg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22ead42c-4d54-47ac-a539-1ef40800a3b4_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>There&#8217;s no proper way for you as a developer to be warned at compile time that you haven&#8217;t handled this case. Nothing is forcing you to properly handle the method&#8217;s exceptions and what&#8217;s worse, unless you dive into each and every method, you&#8217;ll find about such cases a tad too late: at runtime.</p><p>And don&#8217;t get me wrong. This is not a C#-only problem. If you&#8217;re tinkering with JavaScript, you know that it too doesn&#8217;t have a native way to indicate the throws of a function, once you invoke it.</p><p>Promises with no catch will just log silent errors, leading to a terrible user experience. Ever caught yourself annoyed and frantically clicking a button, thinking it did nothing? Of course you did.</p><p>                                                                     ***</p><p>I think by now it&#8217;s became crystal clear why throwing exceptions is so problematic.</p><h2><strong>So what&#8217;s the alternative?</strong></h2><h1>Enter Result Object</h1><p>In contrast to the traditional exception handling model, adopting result objects for error management offers a more explicit, intuitive, and performant way of handling errors.</p><p>A <code>result </code>object encapsulates the outcome of an operation, clearly distinguishing between success and failure states. This model encourages a more deliberate handling of errors and makes the control flow within applications more transparent.</p><h2>Enhanced Performance</h2><p>Without the need to throw exceptions, the performance overhead associated with them is eliminated. Operations can return result objects directly, bypassing the costly process of exception throwing and catching.</p><h2>Clarity in Control Flow</h2><p>Result objects make the handling of errors a first-class concern in the application flow. This explicitness enhances readability and maintainability, as success and failure paths are clearly delineated within the code.</p><h2>Flexibility and Consistency in Error Handling</h2><p>Using result objects, developers gain flexibility in how and where errors are handled, promoting a consistent approach to error management across the application. This model facilitates easier debugging and testing, as error conditions are explicitly represented in the code.</p><h2>Honest signatures</h2><p>Result objects bring errors out of the shadows, depicting clearly the possibility of one to be returned. This explicitness enhances the self-documenting nature of code and aligns with principles of clean code that advocate for readability and maintainability.</p><h1>Result object example</h1><p>Incorporating result objects into your applications encourages a design that aligns closely with Domain-Driven Design (DDD) principles. By encapsulating success and failure within a single object, you can create a rich model of your application's domain, making the code more intuitive and aligned with business operations and logic.</p><p>Consider a trivial example where a method attempts to validate the properties of a user. Instead of throwing an exception when encountering an error, the method could return a result object indicating the failure and its cause:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CiIU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b413d6-bda3-43d8-be55-ddc89a5d9411_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CiIU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b413d6-bda3-43d8-be55-ddc89a5d9411_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!CiIU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b413d6-bda3-43d8-be55-ddc89a5d9411_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!CiIU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b413d6-bda3-43d8-be55-ddc89a5d9411_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!CiIU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b413d6-bda3-43d8-be55-ddc89a5d9411_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CiIU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b413d6-bda3-43d8-be55-ddc89a5d9411_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/14b413d6-bda3-43d8-be55-ddc89a5d9411_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:539686,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!CiIU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b413d6-bda3-43d8-be55-ddc89a5d9411_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!CiIU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b413d6-bda3-43d8-be55-ddc89a5d9411_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!CiIU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b413d6-bda3-43d8-be55-ddc89a5d9411_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!CiIU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b413d6-bda3-43d8-be55-ddc89a5d9411_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This approach contrasts sharply with traditional exception handling, where the method might throw an exception for the same condition, complicating both the method's implementation and its consumption:</p><p>By using <code>Result</code> object, the method's signature truthfully communicates its behavior to callers, including the potential for failure, without relying on side effects like exceptions. This clarity and honesty in method signatures lead to safer, more reliable code.</p><h1><strong>Conclusion</strong></h1><p>The conventional wisdom surrounding exception handling is due for a reevaluation.</p><p>Exceptions should be reserved for truly exceptional, unpredictable events.</p><p>For routine error handling, especially for known error conditions, result objects offer a superior alternative that is explicit, efficient, and conducive to clearer, more maintainable code.</p><p>Adopting result objects not only improves the performance and reliability of applications but also enhances the developer experience by making error handling a more integral and transparent part of the programming model.</p><p></p><div><hr></div><h1>Pay it forward</h1><p>Here are this week&#8217;s knowledge nuggets that made me pause and think:</p><p><a href="https://substack.com/home/post/p-142552747?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">Design is an Island</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Kent Beck&quot;,&quot;id&quot;:24333739,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F000da410-0ed6-4a25-80b1-6a46e964ae0b_242x242.jpeg&quot;,&quot;uuid&quot;:&quot;c9ab81a8-77cc-4f3d-b6d3-17438aee82a8&quot;}" data-component-name="MentionToDOM"></span> </p><p><a href="https://newsletter.francofernando.com/p/geospatial-indexes?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">Geospatial indexes</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Franco Fernando&quot;,&quot;id&quot;:47169986,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/58a41b86-1e25-4bd0-a448-138d50731db4_800x800.png&quot;,&quot;uuid&quot;:&quot;30cbb281-ef6e-4141-9f43-21270f9a1fd7&quot;}" data-component-name="MentionToDOM"></span> </p><p><a href="https://newsletter.systemdesigncodex.com/p/how-linkedin-uses-caching-for-profile-reads?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">How LinkedIn Uses Caching to Serve 5M Profile Reads/Sec? </a>by</p><p><span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Saurabh Dashora&quot;,&quot;id&quot;:97484183,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9626145f-2837-4635-becf-04a372de29e2_607x607.jpeg&quot;,&quot;uuid&quot;:&quot;e0cb8817-a5db-47e7-b3ca-166d59ecc743&quot;}" data-component-name="MentionToDOM"></span> </p><p><a href="https://substack.com/home/post/p-142395646?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">My learnings from the book "A Philosophy of Software Design" </a>- by</p><p><span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Dr Milan Milanovi&#263;&quot;,&quot;id&quot;:24455408,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/3a792453-001b-4564-9b05-3f2323b46763_1280x1124.png&quot;,&quot;uuid&quot;:&quot;f04a14ad-1491-4caa-95ee-b2ca0a2dbd20&quot;}" data-component-name="MentionToDOM"></span> </p><p><a href="https://www.linkedin.com/posts/goeleven_why-should-you-care-about-web-specifications-activity-7177997660140765184-J-pi?utm_source=share&amp;utm_medium=member_desktop">Why should you care about web specifications?</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Yves Goeleven&quot;,&quot;id&quot;:6964046,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b1ff9e7b-3536-4810-8eba-ca23be492fa4_144x144.png&quot;,&quot;uuid&quot;:&quot;5cb567d6-a37b-46b7-bf16-8d52c0450111&quot;}" data-component-name="MentionToDOM"></span> </p><p></p><div><hr></div><p>If you liked this post, share it with your friends and colleagues.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/p/your-systems-exceptions-are-a-ticking?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thesunshinelayer.com/p/your-systems-exceptions-are-a-ticking?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Sunshine Layer! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[The biggest Obstacle stalling your career growth]]></title><description><![CDATA[Lessons from Black Swans and the importance of continuous learning]]></description><link>https://www.thesunshinelayer.com/p/the-biggest-obstacle-stalling-your</link><guid isPermaLink="false">https://www.thesunshinelayer.com/p/the-biggest-obstacle-stalling-your</guid><dc:creator><![CDATA[Elena Sunshine]]></dc:creator><pubDate>Mon, 18 Mar 2024 05:30:16 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/7b494c7f-7ce5-4e4c-9b90-ab7720371c58_4200x3000.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You and I are wrong, but we don&#8217;t yet know it.</p><p>We move through life with an air of assurance. We wear an invisible robe that whispers:</p><blockquote><p><em><strong>"You're right. About this. About that. About almost everything."</strong></em></p></blockquote><p>Think about it. <strong>We are never wrong in the present.</strong></p><p>We were wrong in the past, oh, naive selves as we were. But NOW we know better. In this present moment, the truth is clear and we know how the world works.</p><p><em><strong>Or do we?</strong></em></p><p>If we pause for a moment to think about it, this notion of near-omniscience is absurd. Yet it so often underpins our thoughts and actions.</p><p>This mindset is where fragility in our understanding of the world stems from.</p><p>I&#8217;m sure you&#8217;ve heard of the term <em><strong>"Black Swan"</strong></em>.</p><p>It used to symbolize something utterly impossible or non-existent. The phrase implied a complete absurdity, a notion so contradictory it was beyond consideration.</p><p>For centuries, a black swan was deemed an impossibility.</p><p>Yet, in 1697, Europeans encountered black swans in Australia, shattering the long-held belief in their non-existence. This event exemplifies that even the most improbable scenarios can occur.</p><p>Despite this lesson, we continue to make numerous <strong>assumptions </strong>daily, considering them<strong> absolute truths</strong>.</p><p>These assumptions shape our perception of reality, often blinding us to the vast array of possibilities beyond our beliefs. Recognizing this tendency is the first step in acknowledging our own limitations and the vastness of what we don't know.</p><p><strong>Okay, what does this have to do with stalling my career?</strong></p><p>This sense of infallibility parallels the <strong>"Expert Beginner"</strong>, also known as <strong>&#8220;Senior Junior&#8221;</strong>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!24Qo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c7fa395-9630-4fca-b406-8a4be9e3726d_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!24Qo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c7fa395-9630-4fca-b406-8a4be9e3726d_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!24Qo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c7fa395-9630-4fca-b406-8a4be9e3726d_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!24Qo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c7fa395-9630-4fca-b406-8a4be9e3726d_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!24Qo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c7fa395-9630-4fca-b406-8a4be9e3726d_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!24Qo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c7fa395-9630-4fca-b406-8a4be9e3726d_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3c7fa395-9630-4fca-b406-8a4be9e3726d_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2506130,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!24Qo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c7fa395-9630-4fca-b406-8a4be9e3726d_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!24Qo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c7fa395-9630-4fca-b406-8a4be9e3726d_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!24Qo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c7fa395-9630-4fca-b406-8a4be9e3726d_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!24Qo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c7fa395-9630-4fca-b406-8a4be9e3726d_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>Throughout my career I interacted with a lot of &#8220;expert beginners&#8221;. Hell, I was one of them. Surely still am to some extent.</p><p>This trap eludes no-one.</p><p><strong>The Expert Beginner</strong> land is the magical <em>(read cursed)</em> place where <strong>developers reach a certain level of proficiency and then stop progressing, believing they've learned all there is to know.</strong></p><p>They stop seeking new knowledge or challenging their understanding, leading to a plateau in skills and awareness.</p><p>They assume their solutions and understandings are nearly <em>always</em> <em>correct</em>, mirroring the general human tendency towards assumed omniscience.</p><p>But this mindset is particularly detrimental in software engineering, where technologies and best practices are constantly evolving.</p><p>Just as the discovery of black swans challenged the universal belief in their nonexistence, breakthroughs in technology frequently overturn established norms in software development.</p><h1><strong>How do you get out of this trap?</strong></h1><h3>1. Embrace Continuous Learning</h3><p>Learning is a never-ending journey. In technology, as in life, there's always something new to discover.</p><p>Carve couple of minutes everyday to read and experiment with technology. If you're not constantly learning, then you're running behind.</p><h3>2. Cultivate Humility</h3><p>Recognize that no matter how much you know, there's always more to learn. The world is vast and complex, and our understanding is inherently limited. You are a student for life.</p><h3>3. Seek Diverse Perspectives</h3><p>Engage with others who have different skills, backgrounds and viewpoints. This will challenge your assumptions and expose you to new ideas and approaches.</p><p>Get out of your bubble or comfort zone. It&#8217;s true what they say. If you feel like the smartest person in the room, you need to switch rooms.</p><h3>4. Reflect and Reassess</h3><p>Regularly take time to reflect on your beliefs and practices. Consider how new information might affect your understanding and be willing to adjust your views accordingly.</p><h3>5. Encourage Constructive Criticism</h3><p>Create an environment where peers can offer feedback and constructive criticism. Being challenged is one of the most effective ways to grow and avoid complacency.</p><h3>6. Experiment and Learn from Failure</h3><p>Don't be afraid to try new things. Yes, you'll be awful at them initially. But don't fear being wrong or making mistakes. Failure is merely an iteration toward proficiency.</p><h1><strong>Conclusion</strong></h1><p>Understanding and mitigating our inherent belief in our own rightness is crucial for personal and professional growth.</p><p><br>That&#8217;s not to say I encourage you to chase after each and every buzzword and hype the tech world concocts on a weekly basis. Fundamentals trump these. However, I encourage you to constantly keep an eye out on what other professionals in the field have to say.</p><p>By embracing humility, continuous learning, and openness to new ideas, we can avoid the pitfalls of the <em><strong>"Expert Beginner"</strong></em> and the assumed omniscience, leading to a more nuanced and expansive understanding of the world and our place within it.</p><p></p><p><strong>P.S.</strong> This train of thought was triggered by reading the book <em><strong>"Being Wrong"</strong></em> by Kathryn Schulz, which I highly recommend.</p><div><hr></div><h1>Pay it forward</h1><p>Having said all these, I decided to introduce a new section to the newsletter.<em>"Pay It Forward"</em>  is where I'll share articles that piqued my curiosity and contributed to my "Today I Learned" moments in the current week.</p><p>Here are this week&#8217;s knowledge nuggets:</p><p><a href="https://substack.com/home/post/p-142183145?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">How Amazon S3 Achieves 99.999999999% Durability</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Neo Kim&quot;,&quot;id&quot;:135589200,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c103940f-0d8b-47e7-9a33-013202e17bb8_389x389.jpeg&quot;,&quot;uuid&quot;:&quot;0481bf0d-19d7-4173-b59e-14834bafca49&quot;}" data-component-name="MentionToDOM"></span> </p><p><a href="https://newsletter.systemdesigncodex.com/p/introduction-to-precaching?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">Introduction to Pre-caching</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Saurabh Dashora&quot;,&quot;id&quot;:97484183,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9626145f-2837-4635-becf-04a372de29e2_607x607.jpeg&quot;,&quot;uuid&quot;:&quot;f11d15f1-0453-4d96-94b8-c1103f9f6ea2&quot;}" data-component-name="MentionToDOM"></span></p><p><a href="https://substack.com/home/post/p-142354607?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">Your ultimate self-confidence toolkit</a> - by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Anemari Fiser&quot;,&quot;id&quot;:107858408,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6250eb47-b5aa-4aa4-9ab2-063611198049_3427x3722.jpeg&quot;,&quot;uuid&quot;:&quot;afc43b4e-0acc-4718-af25-3db08ffb5ead&quot;}" data-component-name="MentionToDOM"></span> </p><p><a href="https://newsletter.eng-leadership.com/p/simplifying-as-much-as-possible-is?r=2appru&amp;utm_campaign=post&amp;utm_medium=web">Simplifying as much as possible is the way to go in the engineering industry</a> by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Gregor Ojstersek&quot;,&quot;id&quot;:106098672,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdbe0558-3b80-4d09-9925-34ff44ed066e_400x400.jpeg&quot;,&quot;uuid&quot;:&quot;c00b9e81-d405-4c8d-a642-b6a3a1c08d38&quot;}" data-component-name="MentionToDOM"></span> </p><div><hr></div><p>If you liked this post, share it with your friends and colleagues.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/p/the-biggest-obstacle-stalling-your?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thesunshinelayer.com/p/the-biggest-obstacle-stalling-your?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Sunshine Layer! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[9 rules for writing cleaner code]]></title><description><![CDATA[Writing code that stands the test of time isn't easy. Find out how practicing object calisthenics will improve your code's structure, readability, and performance.]]></description><link>https://www.thesunshinelayer.com/p/9-rules-for-writing-cleaner-code</link><guid isPermaLink="false">https://www.thesunshinelayer.com/p/9-rules-for-writing-cleaner-code</guid><dc:creator><![CDATA[Elena Sunshine]]></dc:creator><pubDate>Mon, 11 Mar 2024 06:01:09 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/7022d9cc-2018-473c-b1d0-1278928a4450_4200x3000.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Calisthenics, a term derived from the Greek words <em>"kal&#242;s"</em> (beautiful) and <em>"sth&#232;nos"</em> (strength), refers to a form of strength training that emphasizes beauty and strength through exercises requiring minimal or no equipment.</p><p>This principle finds a parallel in software design with Object Calisthenics, a concept introduced by Jeff Bay in <em>"The ThoughtWorks Anthology"</em>. With this adaptation, it consists of a set of nine rules aimed at enhancing code's maintainability, readability, and overall quality by imposing specific constraints.</p><p>The initial idea of the paper was to create a pet project to follow these 9 rules to the teeth, yet the way I see it is that the end goal is to assimilate them as guidelines or, better yet, reflexes, to avoid common pitfalls, promoting a more thoughtful and refined approach to coding.</p><p>These rules encourage us all to write cleaner, more readable, and more maintainable code. Again, even if they may seem restrictive at first, adhering to them will significantly enhance your coding practices.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yNxT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a77fb3f-3658-459f-906c-1b9be738f8b1_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yNxT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a77fb3f-3658-459f-906c-1b9be738f8b1_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!yNxT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a77fb3f-3658-459f-906c-1b9be738f8b1_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!yNxT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a77fb3f-3658-459f-906c-1b9be738f8b1_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!yNxT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a77fb3f-3658-459f-906c-1b9be738f8b1_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yNxT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a77fb3f-3658-459f-906c-1b9be738f8b1_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5a77fb3f-3658-459f-906c-1b9be738f8b1_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:283196,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!yNxT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a77fb3f-3658-459f-906c-1b9be738f8b1_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!yNxT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a77fb3f-3658-459f-906c-1b9be738f8b1_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!yNxT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a77fb3f-3658-459f-906c-1b9be738f8b1_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!yNxT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a77fb3f-3658-459f-906c-1b9be738f8b1_2380x2380.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The rules are:</p><ol><li><p><strong>Use Only One Level of Indentation per Method</strong></p></li><li><p><strong>Don&#8217;t Use the ELSE Keyword</strong></p></li><li><p><strong>Wrap All Primitives and Strings</strong></p></li><li><p><strong>Use First-Class Collections</strong></p></li><li><p><strong>Use Only One Dot per Line</strong></p></li><li><p><strong>Don&#8217;t Abbreviate</strong></p></li><li><p><strong>Keep All Entities Small</strong></p></li><li><p><strong>Don&#8217;t Use Classes with More Than Two Instance Variables</strong></p></li><li><p><strong>Don&#8217;t Use Getters or Setters</strong></p></li></ol><p>Now let's break down these 9 rules:</p><h1><strong>1. Use Only One Level of Indentation per Method</strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HcUw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0607673e-e32f-48e8-b1b0-3f0c8a3b1fd0_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HcUw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0607673e-e32f-48e8-b1b0-3f0c8a3b1fd0_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!HcUw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0607673e-e32f-48e8-b1b0-3f0c8a3b1fd0_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!HcUw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0607673e-e32f-48e8-b1b0-3f0c8a3b1fd0_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!HcUw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0607673e-e32f-48e8-b1b0-3f0c8a3b1fd0_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HcUw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0607673e-e32f-48e8-b1b0-3f0c8a3b1fd0_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0607673e-e32f-48e8-b1b0-3f0c8a3b1fd0_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:896512,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!HcUw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0607673e-e32f-48e8-b1b0-3f0c8a3b1fd0_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!HcUw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0607673e-e32f-48e8-b1b0-3f0c8a3b1fd0_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!HcUw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0607673e-e32f-48e8-b1b0-3f0c8a3b1fd0_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!HcUw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0607673e-e32f-48e8-b1b0-3f0c8a3b1fd0_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This rule enhances readability and maintainability by ensuring methods are concise and focused on a single task &#8212; kind of like reading a document with clear and distinct paragraphs.</p><p>Each method (representing a paragraph) maintains a specific level of abstraction, guiding the reader through the code's logic without overwhelming them with details.</p><p>Adopting this approach not only improves code cohesiveness and reusability, but I also found it simplifies stack tracing and eases understanding by keeping unnecessary details out of a method's concern.</p><p>You might say that this strategy makes is harder to read the whole context of the class, because you have to hop in and out of methods to understand the context. I disagree with this idea, as you are normally reading the code as though it were a set of TO paragraphs, each of which is describing the current level of abstraction and referencing subsequent TO paragraphs at the next level down.</p><p>Sticking by this rule actually facilitates a smoother navigation through code by adhering to a single level of abstraction.</p><p>It's like cooking a lasagna; you don't need to know how to make bechamel sauce from scratch if you're not planning to make it, hence keeping the focus on assembling the lasagna layers.</p><p>Can you tell I&#8217;m hungry as I&#8217;m writing this?</p><h1><strong>2. Don&#8217;t Use the ELSE Keyword</strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ld9W!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff17bc12d-a206-4a65-af41-e359fc9bc61b_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ld9W!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff17bc12d-a206-4a65-af41-e359fc9bc61b_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!ld9W!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff17bc12d-a206-4a65-af41-e359fc9bc61b_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!ld9W!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff17bc12d-a206-4a65-af41-e359fc9bc61b_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!ld9W!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff17bc12d-a206-4a65-af41-e359fc9bc61b_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ld9W!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff17bc12d-a206-4a65-af41-e359fc9bc61b_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f17bc12d-a206-4a65-af41-e359fc9bc61b_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:942556,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ld9W!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff17bc12d-a206-4a65-af41-e359fc9bc61b_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!ld9W!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff17bc12d-a206-4a65-af41-e359fc9bc61b_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!ld9W!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff17bc12d-a206-4a65-af41-e359fc9bc61b_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!ld9W!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff17bc12d-a206-4a65-af41-e359fc9bc61b_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Eschewing the <code>else</code> keyword not only clarifies code and reduces cognitive load, but it also helps in avoiding code duplication.</p><p>By favoring early return statements and leveraging polymorphism for conditional operations, code becomes more linear and less nested.</p><p>This practice leads to a cleaner, more intuitive code structure and reduces the cognitive load off our shoulders. Each decision point is straightforward, enhancing the code's readability and maintainability.</p><h1><strong>3. Wrap All Primitives and Strings</strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0j66!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c0785d-8806-4171-a007-c941cc2bd7b0_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0j66!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c0785d-8806-4171-a007-c941cc2bd7b0_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!0j66!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c0785d-8806-4171-a007-c941cc2bd7b0_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!0j66!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c0785d-8806-4171-a007-c941cc2bd7b0_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!0j66!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c0785d-8806-4171-a007-c941cc2bd7b0_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0j66!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c0785d-8806-4171-a007-c941cc2bd7b0_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d6c0785d-8806-4171-a007-c941cc2bd7b0_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:255242,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0j66!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c0785d-8806-4171-a007-c941cc2bd7b0_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!0j66!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c0785d-8806-4171-a007-c941cc2bd7b0_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!0j66!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c0785d-8806-4171-a007-c941cc2bd7b0_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!0j66!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c0785d-8806-4171-a007-c941cc2bd7b0_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>An <code>int</code>, on its own, is merely a scalar with no meaning. It relies solely on method names to express intent.</p><p>Wrapping primitives in objects not only provides the compiler (and the developers touching the code) with more context about the value's nature and its purpose, but it also facilitates semantically correct programming.</p><p>This encapsulation allows for type hinting and the incorporation of behavior into value objects, overcoming the issue of <em>primitive obsession</em>.</p><p>Through encapsulation, operations related to the value are centralized, enhancing code semantics and utility.</p><h1>4. <strong>Use First-Class Collections</strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qNaN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca874fea-498c-4886-a4c9-9ee55d042616_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qNaN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca874fea-498c-4886-a4c9-9ee55d042616_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!qNaN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca874fea-498c-4886-a4c9-9ee55d042616_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!qNaN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca874fea-498c-4886-a4c9-9ee55d042616_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!qNaN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca874fea-498c-4886-a4c9-9ee55d042616_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qNaN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca874fea-498c-4886-a4c9-9ee55d042616_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ca874fea-498c-4886-a4c9-9ee55d042616_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:454111,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qNaN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca874fea-498c-4886-a4c9-9ee55d042616_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!qNaN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca874fea-498c-4886-a4c9-9ee55d042616_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!qNaN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca874fea-498c-4886-a4c9-9ee55d042616_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!qNaN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca874fea-498c-4886-a4c9-9ee55d042616_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>This rule specifies that any class containing a collection should not have any other member variables. It emphasizing that <strong>each collection deserves its own dedicated home</strong> (class).</p><p>Such encapsulation turns collections into first-class citizens within the domain, providing a clear home for behaviors related to the collection, such as filtering, aggregation, or applying rules to each element.</p><p>Wrapping collections thus not only gives them a more defined structural role in the domain, but also elevates domain-specific concepts, making collections integral and well-defined components of your software's architecture.</p><p>This principle is akin to wrapping primitives, but specifically tailored for collections, ensuring that behaviors have a designated home and that <strong>collections are treated with the same care and consideration as other domain-specific elements</strong>.</p><h1>5. <strong>Use Only One Dot per Line</strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!XSsx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F723fb125-8beb-4fca-a0f2-686478d68d2a_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!XSsx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F723fb125-8beb-4fca-a0f2-686478d68d2a_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!XSsx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F723fb125-8beb-4fca-a0f2-686478d68d2a_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!XSsx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F723fb125-8beb-4fca-a0f2-686478d68d2a_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!XSsx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F723fb125-8beb-4fca-a0f2-686478d68d2a_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!XSsx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F723fb125-8beb-4fca-a0f2-686478d68d2a_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/723fb125-8beb-4fca-a0f2-686478d68d2a_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:857296,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!XSsx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F723fb125-8beb-4fca-a0f2-686478d68d2a_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!XSsx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F723fb125-8beb-4fca-a0f2-686478d68d2a_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!XSsx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F723fb125-8beb-4fca-a0f2-686478d68d2a_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!XSsx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F723fb125-8beb-4fca-a0f2-686478d68d2a_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>It can be quite daunting to decide which object should take responsibility for an action.</p><p>But a great strategy to identify misplaced responsibilities is to search for lines with multiple dots, as these often indicate a violation of encapsulation or a middleman object that knows too much.</p><p>This rule underscores the importance of adhering to the Law of Demeter, advocating for direct communication with an object rather than "poking around" its internals.</p><p>Adhering to this guideline significantly improves readability and debuggability, as it isolates actions to specific lines and makes it easier to pinpoint errors. To better picture this, imagine having a trace that shows an exception on a line with 4 dots.</p><p>Exceptions to this rule include Fluent Interfaces and the Method Chaining Pattern, where the goal is clarity.</p><p>But even then, a better approach is through a "taller" rather than "wider" code structure. This means separating one dot per line to make it easier to reason about and follow.</p><h1><strong>6. Don&#8217;t Abbreviate</strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-TmY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71b26bf3-9872-4b07-823b-6d6b01a3a3f1_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-TmY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71b26bf3-9872-4b07-823b-6d6b01a3a3f1_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!-TmY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71b26bf3-9872-4b07-823b-6d6b01a3a3f1_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!-TmY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71b26bf3-9872-4b07-823b-6d6b01a3a3f1_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!-TmY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71b26bf3-9872-4b07-823b-6d6b01a3a3f1_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-TmY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71b26bf3-9872-4b07-823b-6d6b01a3a3f1_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/71b26bf3-9872-4b07-823b-6d6b01a3a3f1_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:151392,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-TmY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71b26bf3-9872-4b07-823b-6d6b01a3a3f1_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!-TmY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71b26bf3-9872-4b07-823b-6d6b01a3a3f1_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!-TmY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71b26bf3-9872-4b07-823b-6d6b01a3a3f1_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!-TmY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71b26bf3-9872-4b07-823b-6d6b01a3a3f1_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>Naming is one of the most challenging tasks programmers face.</p><p>Abbreviations unfortunately don&#8217;t make this any easier. They obscure meaning and indicate underlying issues like duplication or misplaced responsibilities.</p><p>Resist the urge to abbreviate, as this, most often than not, leads to confusion and hides larger design problems.</p><p>Consider the reason behind the abbreviation desire; it may reveal opportunities to eliminate redundancy or indicate that responsibilities might be better allocated.</p><p>At the other end of the spectrum, avoid over bloating names unnecessarily &#8212; context can often eliminate the need for repetition. For example, within a <code>User</code> class, <code>ID</code> clearly refers to the user&#8217;s ID without needing further specification.</p><p>Striking the right balance in naming fosters clearer communication, reveals deeper design insights, and enhances code readability.</p><h1><strong>7. Keep All Entities Small</strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ucTm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04677dc8-4264-4cd9-a208-cce9b5c118b6_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ucTm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04677dc8-4264-4cd9-a208-cce9b5c118b6_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!ucTm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04677dc8-4264-4cd9-a208-cce9b5c118b6_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!ucTm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04677dc8-4264-4cd9-a208-cce9b5c118b6_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!ucTm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04677dc8-4264-4cd9-a208-cce9b5c118b6_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ucTm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04677dc8-4264-4cd9-a208-cce9b5c118b6_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/04677dc8-4264-4cd9-a208-cce9b5c118b6_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:478638,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ucTm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04677dc8-4264-4cd9-a208-cce9b5c118b6_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!ucTm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04677dc8-4264-4cd9-a208-cce9b5c118b6_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!ucTm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04677dc8-4264-4cd9-a208-cce9b5c118b6_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!ucTm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04677dc8-4264-4cd9-a208-cce9b5c118b6_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>This guideline advocates for no class exceeding 50 lines and no package exceeding ten files. Its end goal is to promote cohesiveness and ease of understanding.</p><p>Its main suggestion is that large classes often undertake multiple responsibilities, detracting from their clarity and reusability.</p><p>As a bonus, small classes benefit from fitting on a single screen, aiding quick comprehension.</p><p>Yes, I know, nowadays we have huge monitors. But I hate squinting, thus I keep my code editor&#8217;s zoom to obnoxious percentages.</p><p>Not gonna lie though, 50 lines can get quite challenging to implement. Yet having this goalpost in mind, helps in creating small, focused classes and leveraging packages for logically grouped behaviors. And this can significantly enhance code quality.</p><p>My personal flavor of this rule though is to focus on method-level, that is aiming for 10 to 15 lines max per method, and adhering to a guideline of no more than five methods per class. I found that this helps prevent violation of the Single Responsibility Principle (SRP), avoiding "god classes" and ensuring shorter dependencies.</p><h1>8. <strong>Don&#8217;t Use Classes with More Than Two Instance Variables</strong></h1><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!i9g2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe0248a6-a4ae-4ee0-bd2d-1f1fccdcd6d6_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!i9g2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe0248a6-a4ae-4ee0-bd2d-1f1fccdcd6d6_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!i9g2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe0248a6-a4ae-4ee0-bd2d-1f1fccdcd6d6_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!i9g2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe0248a6-a4ae-4ee0-bd2d-1f1fccdcd6d6_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!i9g2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe0248a6-a4ae-4ee0-bd2d-1f1fccdcd6d6_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!i9g2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe0248a6-a4ae-4ee0-bd2d-1f1fccdcd6d6_1427x1427.gif" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fe0248a6-a4ae-4ee0-bd2d-1f1fccdcd6d6_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:808761,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!i9g2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe0248a6-a4ae-4ee0-bd2d-1f1fccdcd6d6_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!i9g2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe0248a6-a4ae-4ee0-bd2d-1f1fccdcd6d6_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!i9g2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe0248a6-a4ae-4ee0-bd2d-1f1fccdcd6d6_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!i9g2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe0248a6-a4ae-4ee0-bd2d-1f1fccdcd6d6_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p></p><p>This rule works as a caution against mixing responsibilities. Consider it a manifesto to preserve class cohesion.</p><p>It encourages limiting classes to two instance variables to foster an effective object model and SRP adherence. Adding more instance variables generally decreases cohesion, prompting a thoughtful decomposition into a hierarchy of collaborating objects.</p><p>This principle aids in simplifying complex object models, ensuring behavior aligns naturally with the appropriate class, bolstered by the compiler and encapsulation rules.</p><p>Again, here as well I find that the rule is quite strict, but it is so for the sake of the exercise &#8212; to get you in the right mindset when writing production code.</p><p>Nonetheless we must all recognize the necessity of flexibility. Instances where more variables are logically cohesive can deviate from this strict guideline.</p><p>My personal rule of thumb is to stick to 5 instance variables, but then again, it&#8217;s a rule of thumb, not something set in stone. It&#8217;s rather something to raise your awareness and start questioning whether that class still respects the SRP principle or not.</p><h1>9. <strong>Don&#8217;t Use Getters or Setters</strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Maqs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb54eea5-ee38-4f10-a06c-89f671229512_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Maqs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb54eea5-ee38-4f10-a06c-89f671229512_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!Maqs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb54eea5-ee38-4f10-a06c-89f671229512_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!Maqs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb54eea5-ee38-4f10-a06c-89f671229512_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!Maqs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb54eea5-ee38-4f10-a06c-89f671229512_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Maqs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb54eea5-ee38-4f10-a06c-89f671229512_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bb54eea5-ee38-4f10-a06c-89f671229512_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:524038,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Maqs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb54eea5-ee38-4f10-a06c-89f671229512_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!Maqs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb54eea5-ee38-4f10-a06c-89f671229512_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!Maqs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb54eea5-ee38-4f10-a06c-89f671229512_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!Maqs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb54eea5-ee38-4f10-a06c-89f671229512_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>This guideline is built directly on the principle of strong encapsulation from the previous rule. It seeks to ensure behaviors remain closely aligned with their respective instance variables, reducing direct access to object states.</p><p>This approach aims to centralize behavior in the object model, leading to less duplication, fewer errors, and easier implementation of new features.</p><p>Emphasizing the principle of <em><strong>"Tell, don&#8217;t ask"</strong></em>, it encourages <strong>designing objects that manage their own data, fostering strong encapsulation.</strong></p><p>I find this particularly beneficial in Domain-Driven Design (DDD) for modeling domain entities. When working with DTO&#8217;s or contracts from APIs, I find it harder to apply this rule. Even so though, I try to stick to private setters instead of opening the gates to unwelcomed alterations, to maintain encapsulation without overly restricting data access.</p><p></p><p>As if all of these 9 rules weren&#8217;t enough, I feel at liberty of adding a 10th one:</p><h1><strong>10. Don&#8217;t Use Comments to Justify Bad Code</strong></h1><p>Comments should not be used as a crutch for poor code; instead, the code should be refactored to address underlying issues directly.</p><p>The only exceptions for comments are to clarify unconventional decisions or to provide summaries in public libraries.</p><p>TODO&#8217;s are accepted, as long as they don&#8217;t make it to the main branch.</p><p>If it&#8217;s something that cannot be done in the current feature, add a task or a story on your project&#8217;s backlog. I found that having such TODOs in the code is simply useless, as they will just get old, unprioritized and forgotten in the code.</p><h1>Conclusion</h1><p>These rules, as outlined by Jeff Bay, serve as an exercise to strengthen your coding reflexes and intuition, just like physical calisthenics enhance your body&#8217;s flexibility and mobility.</p><p>While there may be contradictions or challenges in applying these rules universally, the intent is to foster a mindset conducive to writing better code.</p><p>It's about finding a balance, using the rules to guide but not constrain and integrating them as they fit comfortably into your development practices, ultimately refining your approach to coding in real-life production scenarios.</p><p></p><div><hr></div><p>P.S. If you liked this post, share it with your friends and colleagues.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/p/9-rules-for-writing-cleaner-code?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thesunshinelayer.com/p/9-rules-for-writing-cleaner-code?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Sunshine Layer! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Economics of coding]]></title><description><![CDATA[How to achieve peak performance in code.]]></description><link>https://www.thesunshinelayer.com/p/economics-of-coding</link><guid isPermaLink="false">https://www.thesunshinelayer.com/p/economics-of-coding</guid><dc:creator><![CDATA[Elena Sunshine]]></dc:creator><pubDate>Mon, 04 Mar 2024 05:30:42 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/ce0dab3f-b3d0-430a-91f5-a34c176077cb_4200x3000.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ever hit a point where optimizing your code started yielding diminishing returns or even made things worse?</p><p>This reality closely mirrors an important economic principle: <strong>the</strong> <strong>Laffer Curve</strong>.</p><p><strong>The Laffer Curve</strong> illustrates the relationship between tax rates and tax revenue.</p><p>It posits that starting from a 0% tax rate, increasing tax rates will also increase revenue.</p><p>But that happens only up to a point.</p><p>Contrary to what some believe, <strong>it&#8217;s not a straight line</strong>. <strong>It&#8217;s a curve</strong>.</p><p>Beyond this peak, further increases in tax rates actually decrease revenue, as they discourage earning or promote tax evasion to reduce overall revenue.</p><p>The curve demonstrates that there's an optimal tax rate that maximizes revenue without discouraging economic activity.</p><p>This goes to show that <strong>every system has its optimal point.</strong></p><p></p><p>If we return to our initial optimization question, we can easily see the resemblance.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0JQ2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb14e998a-d2f6-4d72-9736-6e505ca37259_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0JQ2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb14e998a-d2f6-4d72-9736-6e505ca37259_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!0JQ2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb14e998a-d2f6-4d72-9736-6e505ca37259_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!0JQ2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb14e998a-d2f6-4d72-9736-6e505ca37259_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!0JQ2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb14e998a-d2f6-4d72-9736-6e505ca37259_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0JQ2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb14e998a-d2f6-4d72-9736-6e505ca37259_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b14e998a-d2f6-4d72-9736-6e505ca37259_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:802833,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0JQ2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb14e998a-d2f6-4d72-9736-6e505ca37259_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!0JQ2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb14e998a-d2f6-4d72-9736-6e505ca37259_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!0JQ2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb14e998a-d2f6-4d72-9736-6e505ca37259_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!0JQ2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb14e998a-d2f6-4d72-9736-6e505ca37259_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Too little optimization and your application drags.</strong></p><p><strong>Too much, and you&#8217;re in a quagmire of complexity.</strong></p><div class="pullquote"><p><strong>Which way you should go depends heavily on where you currently stand.</strong></p></div><h3>Over-optimization</h3><p><em>Sky-high tax rates will eventually halt economic activity.</em></p><p>Like setting tax rates without economic understanding, optimizing without profiling is flying blind. It can lead to wasted efforts on parts of your code that don&#8217;t actually need it.</p><p>Think <em><strong>premature optimization</strong></em>. Pushing for optimization at every turn decreases overall productivity and hampers software maintainability.</p><h3>Under-optimization</h3><p><em>Low tax rates miss out on important revenue.</em></p><p>Under-optimized code can lead to lackluster performance. Although speedy at first, code that is not cared for is guaranteed to become a big ball of mud.</p><p></p><h2>How to find the sweet spot</h2><h3>Measure and monitor</h3><p><em>Determining optimal tax rates demands understanding of the economy.</em></p><p>In the same vein, you need to dive into the domain first to find bottlenecks and hot points. Profiling tools and benchmarks help you to understand where the hot points, worth optimizing, are.</p><h3>Understand the law of diminishing returns</h3><p><em>The Laffer Curve hints at evaluating trade-offs.</em></p><p>In code there&#8217;s a balance between performance and maintainability. Aim for the right level of optimization that provides both speed and clarity. Not all effort is equally fruitful.</p><h3>Consider maintainability</h3><p><em>Too high or too low taxes lead to long-term economic damage.</em></p><p>Both overly optimized code and spaghetti balls of mud are hard to maintain and cause issues down the line.</p><p>Pushing for extreme performance can make your code unreadable. Like high tax rates stifle business, dense code stifles collaboration and future changes.</p><h3>Iterate and refine</h3><p><em>Tax policies often need tweaks and revisions based on changing economic conditions.</em></p><p>Similarly, as your software evolves and grows, revisit optimization decisions.</p><p></p><h2>Conclusion</h2><p>Just like economics, code is an ecosystem. You can think of your codebase like an economy. It has its resources (data), processes (algorithms) and agents (functions).</p><p>Overburdening any aspect, like with excessive optimization, can disrupt the harmony.</p><p>Just as policymakers use the Laffer Curve to inform decisions, let balance guide your coding strategy.</p><p>The best performance comes from equilibrium. Not extremes.</p><p></p><div><hr></div><p>P.S. If you liked this post, share it with your friends and colleagues.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/p/economics-of-coding?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thesunshinelayer.com/p/economics-of-coding?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Sunshine Layer! Subscribe for free to receive new software insights every week.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[5 Deployment strategies that make your life easier]]></title><description><![CDATA[Dreading the next big update? Find out how the right deployment strategy can transform update day from a nightmare into a non-event for your team.]]></description><link>https://www.thesunshinelayer.com/p/5-deployment-strategies-that-make</link><guid isPermaLink="false">https://www.thesunshinelayer.com/p/5-deployment-strategies-that-make</guid><dc:creator><![CDATA[Elena Sunshine]]></dc:creator><pubDate>Mon, 26 Feb 2024 05:30:14 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/a1c9a622-c36a-46e7-a6ec-4fb1b7af515a_4200x3000.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Tired of holding your breath every time you push an update?</strong></p><p>Deploying new versions of applications or features is a crucial aspect of software development, but <strong>they don&#8217;t have to be a pain</strong>.</p><p>You just need to carefully choose the right strategy for your project.</p><p>The right deployment strategy minimizes downtime and bugs, enhancing user experience, while a poor choice can lead to significant issues, including customer dissatisfaction and money down the drain.</p><p>Here's an in-depth look at <strong>five key deployment strategies,</strong> highlighting how each manages risk, user experience, and feedback during the deployment process:</p><p><strong>&#8594; Big-Bang Deployment</strong></p><p><strong>&#8594; Blue-Green Deployment</strong></p><p><strong>&#8594; Rolling Deployment</strong></p><p><strong>&#8594; Canary Deployment</strong></p><p><strong>&#8594; Ring Deployment</strong></p><h1>Big-Bang Deployment</h1><p>This strategy, alternatively known as the the <strong>Recreate deployment</strong> strategy, involves a straightforward approach to updating applications by sequentially <em>shutting down the current version</em> <em><strong>(Version A)</strong> and then deploying the new version</em> <em><strong>(Version B)</strong></em>.</p><p>It is characterized by its simplicity, but inherently <strong>implies a period of downtime for the service</strong>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hhse!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd07e8c7c-1d57-4c5d-b0d7-5631d1e13db9_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hhse!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd07e8c7c-1d57-4c5d-b0d7-5631d1e13db9_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!hhse!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd07e8c7c-1d57-4c5d-b0d7-5631d1e13db9_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!hhse!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd07e8c7c-1d57-4c5d-b0d7-5631d1e13db9_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!hhse!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd07e8c7c-1d57-4c5d-b0d7-5631d1e13db9_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hhse!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd07e8c7c-1d57-4c5d-b0d7-5631d1e13db9_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d07e8c7c-1d57-4c5d-b0d7-5631d1e13db9_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1966655,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!hhse!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd07e8c7c-1d57-4c5d-b0d7-5631d1e13db9_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!hhse!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd07e8c7c-1d57-4c5d-b0d7-5631d1e13db9_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!hhse!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd07e8c7c-1d57-4c5d-b0d7-5631d1e13db9_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!hhse!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd07e8c7c-1d57-4c5d-b0d7-5631d1e13db9_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><strong>Process</strong></h3><ol><li><p><strong>Shutdown of Current Version</strong></p><p>The process begins with the shutdown of Version A, the current live version of the application. This step is critical and marks the start of the deployment's downtime.</p></li><li><p><strong>Deployment of New Version</strong></p><p>Following the complete shutdown of Version A, Version B is deployed. The duration of the deployment, including the boot time for Version B, directly contributes to the total downtime experienced.</p></li><li><p><strong>Service Restoration</strong></p><p>Once Version B is successfully deployed and operational, the service becomes available to users again, marking the end of the deployment process.</p></li></ol><h3><strong>Advantages</strong></h3><h4><strong>Simplicity</strong></h4><p>The recreate strategy is straightforward to understand and implement, requiring fewer steps and less complexity in comparison to strategies that involve parallel environments or incremental rollouts.</p><h4><strong>Clear Transition</strong></h4><p>It provides a clean slate for the new version, eliminating potential conflicts or complexities that might arise from concurrent versions.</p><h3><strong>Challenges</strong></h3><h4><strong>Downtime</strong></h4><p>The most significant drawback of this strategy is the <strong>inevitable service downtime</strong>, the duration of which depends on the shutdown and boot times of the application.</p><p>Effective use of the recreate strategy necessitates careful planning to minimize the impact of downtime, possibly scheduling deployments during off-peak hours.</p><h4><strong>Risk Management</strong></h4><p>The ability to <em><strong>quickly rollback in case of issues with Version B is limited</strong></em>, as it would require repeating the process in reverse, further extending downtime.</p><p>Strategies to mitigate the risks associated with this approach include thorough pre-deployment testing of Version B and preparing a rollback version in advance, should an immediate switch back become necessary.</p><p></p><p>The Big-Bang Deployment strategy' simplicity makes it a viable option for certain scenarios, particularly those where <em><strong>service continuity is not critically time-sensitive</strong></em> or where application architecture does not support more complex deployment methods.</p><p>However, the inherent downtime and risk factors require careful consideration and planning to ensure a successful update process.</p><p></p><h1>Blue-Green Deployment</h1><p>This approach employs two identical production environments, named <strong>Blue and Green</strong>, to facilitate updates with zero downtime.</p><p>It ensures a seamless user experience by allowing one environment to be live while <em>the other is prepared</em> <em>with the new version</em>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZSsa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54da22cb-fdf8-4745-b08f-69c4dd6a6b86_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZSsa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54da22cb-fdf8-4745-b08f-69c4dd6a6b86_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!ZSsa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54da22cb-fdf8-4745-b08f-69c4dd6a6b86_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!ZSsa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54da22cb-fdf8-4745-b08f-69c4dd6a6b86_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!ZSsa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54da22cb-fdf8-4745-b08f-69c4dd6a6b86_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZSsa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54da22cb-fdf8-4745-b08f-69c4dd6a6b86_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/54da22cb-fdf8-4745-b08f-69c4dd6a6b86_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1829651,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ZSsa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54da22cb-fdf8-4745-b08f-69c4dd6a6b86_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!ZSsa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54da22cb-fdf8-4745-b08f-69c4dd6a6b86_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!ZSsa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54da22cb-fdf8-4745-b08f-69c4dd6a6b86_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!ZSsa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54da22cb-fdf8-4745-b08f-69c4dd6a6b86_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><strong>Process</strong></h3><ol><li><p><strong>Initial Setup</strong></p><p>The Blue environment serves as the active site, delivering the current live version to users, while the Green environment is set up but remains idle.</p></li><li><p><strong>Deployment to Green</strong></p><p>The new application version is deployed to the Green environment, allowing the Blue environment to continue serving users without interruption.</p></li><li><p><strong>Quality Assurance</strong></p><p>The QA team tests the new version in the Green environment, identifying and resolving any issues. This stage is crucial for ensuring the new version's readiness without impacting the live user experience.</p></li><li><p><strong>Traffic Switch</strong></p><p>Once the new version is deemed ready, the load balancer redirects traffic from the Blue to the Green environment. This switch is instantaneous, transitioning users to the new version with no perceived downtime.</p></li><li><p><strong>Safety Net</strong></p><p>Post-switch, the Blue environment becomes the idle environment, ready to be activated if a need for rollback arises due to unforeseen issues with the new version.</p></li></ol><h3><strong>Advantages</strong></h3><h4><strong>Zero Downtime</strong></h4><p>Ensures continuous service availability during updates.</p><h4><strong>Seamless User Transition</strong></h4><p>Users are moved to the new version without any disruption to their service.</p><h4><strong>Instant Rollback</strong></h4><p>Provides a quick fallback to the previous version if the new deployment encounters issues, enhancing reliability.</p><h3><strong>Challenges</strong></h3><h4><strong>Resource Intensive</strong></h4><p>Requires double the infrastructure, increasing operational costs and resource needs.</p><h4><strong>Complexity in Management</strong></h4><p>The need to <em><strong>maintain two parallel production environments</strong></em> introduces complexity, especially in ensuring data synchronization and seamless transitions.</p><h4><strong>Unified Switch</strong></h4><p>The switch from Blue to Green applies to all users simultaneously, unlike strategies that allow for targeted user exposure.</p><p></p><p>Blue-Green Deployment optimizes for uptime and rollback capabilities, presenting a robust strategy for managing deployments with minimal user disruption.</p><p>Despite its <strong>resource intensity and the complexity</strong> it introduces, <strong>the high level of control and minimized risk make Blue-Green Deployment a favored strategy</strong> for achieving a smooth user experience and ensuring reliable rollbacks.</p><p></p><h1>Rolling Deployment</h1><p>This strategy, also referred to as the <em><strong>ramped deployment</strong></em> method, is tailored for environments with multiple instances, where updates are applied gradually by replacing old version instances with new version instances.</p><p>This method ensures <strong>continuous service availability and minimizes user disruption</strong>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!X6p0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe0dff1-c9eb-43e8-bc6e-0998ca1b0041_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!X6p0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe0dff1-c9eb-43e8-bc6e-0998ca1b0041_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!X6p0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe0dff1-c9eb-43e8-bc6e-0998ca1b0041_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!X6p0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe0dff1-c9eb-43e8-bc6e-0998ca1b0041_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!X6p0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe0dff1-c9eb-43e8-bc6e-0998ca1b0041_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!X6p0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe0dff1-c9eb-43e8-bc6e-0998ca1b0041_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cbe0dff1-c9eb-43e8-bc6e-0998ca1b0041_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:899506,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!X6p0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe0dff1-c9eb-43e8-bc6e-0998ca1b0041_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!X6p0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe0dff1-c9eb-43e8-bc6e-0998ca1b0041_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!X6p0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe0dff1-c9eb-43e8-bc6e-0998ca1b0041_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!X6p0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe0dff1-c9eb-43e8-bc6e-0998ca1b0041_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><strong>Process</strong></h3><ol><li><p><strong>Starting Point</strong></p><p>Initially, all instances run the old version (Version A) and are capable of handling user requests. This capacity is crucial to maintain service availability as instances are updated.</p></li><li><p><strong>Introduction of New Instance</strong></p><p>A new instance running the updated version (Version B) is created and replaced in the pool, beginning to serve user requests alongside existing Version A instances.</p></li><li><p><strong>Phased Replacement</strong></p><p>Subsequently, instances running Version A are gradually replaced with instances running Version B. This step is carefully managed to ensure that the system can support simultaneous operation of both versions without service degradation.</p></li><li><p><strong>Continuous Operation and Testing</strong></p><p>Throughout this process, the remaining Version A instances must be capable of serving all user requests to prevent downtime. Continuous testing during the update ensures that the application performs as expected.</p></li><li><p><strong>Completion</strong></p><p>The update concludes when all instances have been replaced with Version B and the application has been validated for proper functionality. Should any issues arise during the deployment, there's the option to roll back to Version A across all instances.</p></li></ol><h3><strong>Advantages</strong></h3><h4><strong>Service Continuity</strong></h4><p>By updating instances incrementally, the application remains available, preventing downtime.</p><h4><strong>Version Compatibility</strong></h4><p>Supports the simultaneous operation of different application versions, facilitating a smoother transition.</p><h4><strong>Flexibility</strong></h4><p>Parameters such as the number of instances updated at a time can be tailored to the application's needs, offering control over the deployment process.</p><h3><strong>Challenges</strong></h3><h4><strong>Complex Version Management</strong></h4><p>Requires the application to support running multiple versions concurrently, which may introduce complexity in ensuring compatibility and seamless operation.</p><h4><strong>Deployment Duration</strong></h4><p>The phased approach extends the total deployment time, especially for applications with a large number of instances.</p><p>Utilizing automation tools can significantly streamline the rolling update process, ensuring efficient management of instance replacement and scaling.</p><h4><strong>Rollback Time</strong></h4><p>While rollback capabilities are inherent, the process to revert all instances to the previous version can be time-consuming.</p><h3></h3><p>The Rolling Deployment strategy offers a balanced approach to software updates, combining <strong>reduced downtime with increased control over the deployment process.</strong></p><p>Its advantages in maintaining service availability and mitigating risks make it a <strong>favored choice</strong> <strong>for </strong>many <strong>applications</strong>, especially those <strong>requiring high availability.</strong></p><p>However, the inherent challenges and complexity necessitate careful planning, coordination, and the use of sophisticated deployment tools to execute successfully.</p><h1>Canary Deployment</h1><p>This is a strategic methodology employed to <strong>introduce a new version of software to a limited subset of users or servers before a full-scale rollout</strong>.</p><p>This approach is named after the <em>historical use of <strong>canaries in coal mines</strong> to detect toxic gases</em>, serving as an early warning to detect potential issues with minimal impact.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jDXV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc047cd2a-99b2-41e2-a82e-cc87f0ed1ba9_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jDXV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc047cd2a-99b2-41e2-a82e-cc87f0ed1ba9_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!jDXV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc047cd2a-99b2-41e2-a82e-cc87f0ed1ba9_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!jDXV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc047cd2a-99b2-41e2-a82e-cc87f0ed1ba9_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!jDXV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc047cd2a-99b2-41e2-a82e-cc87f0ed1ba9_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jDXV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc047cd2a-99b2-41e2-a82e-cc87f0ed1ba9_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c047cd2a-99b2-41e2-a82e-cc87f0ed1ba9_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1837206,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!jDXV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc047cd2a-99b2-41e2-a82e-cc87f0ed1ba9_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!jDXV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc047cd2a-99b2-41e2-a82e-cc87f0ed1ba9_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!jDXV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc047cd2a-99b2-41e2-a82e-cc87f0ed1ba9_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!jDXV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc047cd2a-99b2-41e2-a82e-cc87f0ed1ba9_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><strong>Process</strong></h3><ol><li><p><strong>Initial Deployment</strong></p><p>A small portion of the production environment, let&#8217;s say 25%, is updated to the new version, serving a select group of users. This group, the "canary," is carefully chosen to represent the broader user base.</p></li><li><p><strong>Monitoring and Feedback</strong></p><p>The performance, stability and overall user experience of the new version are closely monitored. Feedback during this phase is critical for identifying any issues early on.</p></li><li><p><strong>Incremental Rollout</strong></p><p>Depending on the initial feedback, the deployment is gradually extended to more users: 50%, 75%... This step-by-step approach allows for continuous monitoring and assessment of the new version's impact.</p></li><li><p><strong>Full Deployment</strong></p><p>If the new version proves to be stable and improvements are consistently positive, it is then rolled out entirely, completing the deployment process.</p></li></ol><h3><strong>Advantages</strong></h3><h4><strong>Risk Reduction</strong></h4><p>The strategy allows for targeted selection of the initial user groups or servers, enabling a controlled and insightful early assessment.</p><p>Limiting the initial deploy to a small percentage minimizes the potential impact of unforeseen issues, making it easier to address problems without affecting the entire system.</p><h4><strong>Deployment Control</strong></h4><p>The pace and scope of the deployment can be dynamically adjusted based on real-time feedback and performance indicators.</p><h3><strong>Challenges</strong></h3><h4><strong>Segmentation and Monitoring Complexity</strong></h4><p>Effectively selecting a representative canary group and closely monitoring their experience requires sophisticated tooling and analytics capabilities.</p><h4><strong>Limited Initial Impact</strong></h4><p>While the strategy aims to mitigate risk, any issues in the new version can still negatively affect the experience of the canary group.</p><h4><strong>Rollback Strategy</strong></h4><p>Should the new version encounter significant issues, a rollback plan is essential.</p><p>This involves gradually decreasing the exposure of the new version, similar to the rollout but in reverse, ensuring a smooth transition back to the previous version.</p><p></p><p>By meticulously introducing a new version to a subset of instances and expanding based on successful performance and feedback, the Canary Deployment strategy offers a <strong>prudent approach</strong> to software updates.</p><p>This method <strong>prioritizes user experience and system stability</strong>, ensuring that any new deploy contributes positively to the product's overall quality and reliability.</p><p></p><h1>Ring Deployment</h1><p>Also known as <em><strong>phased or progressive deployment</strong></em>, this is a strategy that introduces a new version of software to users in stages, based on predefined groups or "rings".</p><p>Each <strong>ring represents a segment of the user base or infrastructure</strong>, with the update progressively reaching broader audiences after successful validation at each phase.</p><p>This method allows for detailed monitoring and targeted feedback, reducing the risk of negative impacts from new deploys.</p><p></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xvq0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbce49869-38ba-4882-abdb-227e9032ae9b_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xvq0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbce49869-38ba-4882-abdb-227e9032ae9b_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!xvq0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbce49869-38ba-4882-abdb-227e9032ae9b_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!xvq0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbce49869-38ba-4882-abdb-227e9032ae9b_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!xvq0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbce49869-38ba-4882-abdb-227e9032ae9b_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xvq0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbce49869-38ba-4882-abdb-227e9032ae9b_1427x1427.gif" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bce49869-38ba-4882-abdb-227e9032ae9b_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3207461,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xvq0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbce49869-38ba-4882-abdb-227e9032ae9b_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!xvq0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbce49869-38ba-4882-abdb-227e9032ae9b_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!xvq0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbce49869-38ba-4882-abdb-227e9032ae9b_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!xvq0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbce49869-38ba-4882-abdb-227e9032ae9b_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p></p><h3><strong>Process</strong></h3><ol><li><p><strong>Segmentation</strong></p><p>The infrastructure is divided into distinct segments, each forming a ring. These segments can be based on various factors, such as user roles, geographical locations or system criticality.</p></li><li><p><strong>Initial Deployment</strong></p><p>The new version is first deployed to the innermost ring, often consisting of internal users, testers or a small, controlled external group. This stage allows for close monitoring and rapid issue identification.</p></li><li><p><strong>Gradual Expansion</strong></p><p>Following successful validation in the initial ring, the deployment expands to subsequent rings, gradually increasing the user base exposed to the new version. Each expansion is contingent on the successful performance and stability of the software in the preceding ring.</p></li><li><p><strong>Final Rollout</strong></p><p>After passing through all the rings successfully, the new version is made available to the entire user base, completing the deployment process.</p></li></ol><h3><strong>Advantages</strong></h3><h4><strong>Incremental Risk Management</strong></h4><p>By staging the rollout across different rings, potential issues can be isolated and addressed with minimal impact, enhancing overall system stability.</p><p>The number and criteria for each ring can be adjusted based on deployment goals and user feedback, offering flexibility in how the deployment is structured.</p><p>There is also a lot of flexibility in regards to the speed at which the deployment moves from one ring to the next can be controlled, allowing adjustments based on observed performance and user feedback.</p><h4><strong>Enhanced User Experience</strong></h4><p>Feedback is more manageable and actionable when collected from specific user groups, facilitating targeted improvements and adjustments.</p><p>Users benefit from a more reliable introduction of new features or versions, with issues likely identified and resolved before reaching the majority.</p><h3><strong>Challenges</strong></h3><h4><strong>Complexity in Management</strong></h4><p>Orchestrating a ring deployment requires detailed planning and coordination, increasing the complexity of the deployment process.</p><p>Like Canary Deployments, ring deployments facilitate easier rollback if issues are identified in later rings, minimizing potential disruption, but having such a plan in place is required.</p><h4><strong>Extended Deployment Time</strong></h4><p>The phased nature of ring deployments can extend the overall timeline for achieving full rollout, potentially delaying the availability of new features to all users.</p><p>Each phase of the deployment may require additional resources for monitoring and support, impacting overall resource allocation.</p><h3></h3><p>Ring Deployment stands out as a strategic approach designed to <strong>balance the introduction of new software versions with the need for stability</strong> and user satisfaction.</p><p>By leveraging detailed segmentation and phased rollouts, organizations can effectively manage the risks associated with software updates, ensuring that new deploys are both robust and well-received by users.</p><p></p><h2>Conclusion</h2><p>Selecting an effective deployment strategy depends on balancing your project's priorities: speed, risk, user impact, and resource allocation.</p><p><strong>&#8226; Big-Bang</strong> <strong>Deployment</strong> offers a straightforward update process when downtime is manageable.</p><p><strong>&#8226; Blue-Green Deployment</strong> is ideal for zero downtime and easy rollbacks, suited for resource-rich environments.</p><p><strong>&#8226; Rolling Deployment</strong> offers a compromise between continuous service and efficiency, perfect for gradual updates across multiple instances.</p><p><strong>&#8226; Canary Deployment</strong> allows for real-world testing on a small scale, optimizing for early issue detection.</p><p><strong>&#8226; Ring Deployment</strong> provides detailed feedback through phased rollouts across segmented user groups, ideal for complex systems.</p><p>The choice should align with your operational capabilities and risk tolerance, ensuring updates enhance both user experience and system reliability.</p><p></p><h4>P.S.</h4><p>One important thing to note is that <strong>deploying </strong>(the process of implementing code in test or live environments)<strong> is not the same as releasing </strong>(the process of making the version available to end-users). But more on that in a <em><strong>future</strong></em> post.</p><p></p><div><hr></div><p>P.P.S. If you liked this post, share it with your friends and colleagues.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/p/5-deployment-strategies-that-make?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thesunshinelayer.com/p/5-deployment-strategies-that-make?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Sunshine Layer! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p><p></p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Bus Factor explained]]></title><description><![CDATA[Why being replaceable is a career booster, not a setback.]]></description><link>https://www.thesunshinelayer.com/p/bus-factor-explained</link><guid isPermaLink="false">https://www.thesunshinelayer.com/p/bus-factor-explained</guid><dc:creator><![CDATA[Elena Sunshine]]></dc:creator><pubDate>Mon, 19 Feb 2024 05:30:35 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/d64f5c8f-6b56-41b4-8378-849d984d779e_4200x3000.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Making yourself replaceable might seem counterintuitive, but it's the key to a resilient team.</p><p>Here's why.</p><p><strong>The Bus Factor</strong> poses the question:</p><div class="pullquote"><p><em><strong>"How many people need to be hit by a bus before the project is in serious trouble?&#8221;</strong></em></p></div><p>Or, more specifically, whose absence would jeopardize the project?</p><p>While it may sound morbid (or hilarious, as many terms in software industry), <em><strong>the bus factor assesses the risk of having crucial knowledge and skills concentrated in a few team members.</strong></em></p><p>A vital factor for project continuity.</p><p>It&#8217;s all about addressing those areas of code where the team replies:</p><blockquote><p><em><strong>"Oh, that feature?</strong></em></p><p><em><strong>It&#8217;s Johnny&#8217;s feature, only him knows how that works."</strong></em></p></blockquote><p>You might think being indispensable is beneficial.</p><p>After all, they can't fire you if you're the sole keeper of knowledge, right?</p><p><strong>Right?</strong></p><p>If you&#8217;re in this camp, there&#8217;s disappointing news ahead: <em><strong>hoarding knowledge will also trap YOU</strong></em>.</p><p>If you're irreplaceable, promotions will easily pass you by. You could miss out on new projects because your presence is crucial in the current one.</p><p>Additionally, imagine the chaos when something goes wrong while you're on vacation. You don't want that call to happen, do you?</p><p>For freelancers, this can affect client referrals. No client wants to risk their project stalling because they shared you with others.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cRlt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b98f82-d008-4c1f-bbf4-cc9628d949c5_713x713.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cRlt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b98f82-d008-4c1f-bbf4-cc9628d949c5_713x713.gif 424w, https://substackcdn.com/image/fetch/$s_!cRlt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b98f82-d008-4c1f-bbf4-cc9628d949c5_713x713.gif 848w, https://substackcdn.com/image/fetch/$s_!cRlt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b98f82-d008-4c1f-bbf4-cc9628d949c5_713x713.gif 1272w, https://substackcdn.com/image/fetch/$s_!cRlt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b98f82-d008-4c1f-bbf4-cc9628d949c5_713x713.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cRlt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b98f82-d008-4c1f-bbf4-cc9628d949c5_713x713.gif" width="713" height="713" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a7b98f82-d008-4c1f-bbf4-cc9628d949c5_713x713.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:713,&quot;width&quot;:713,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:848422,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cRlt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b98f82-d008-4c1f-bbf4-cc9628d949c5_713x713.gif 424w, https://substackcdn.com/image/fetch/$s_!cRlt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b98f82-d008-4c1f-bbf4-cc9628d949c5_713x713.gif 848w, https://substackcdn.com/image/fetch/$s_!cRlt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b98f82-d008-4c1f-bbf4-cc9628d949c5_713x713.gif 1272w, https://substackcdn.com/image/fetch/$s_!cRlt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b98f82-d008-4c1f-bbf4-cc9628d949c5_713x713.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>So, what can you do?</p><h4><strong>&#8594; Document Processes</strong></h4><p>Keep thorough documentation for critical tasks and processes.</p><h4><strong>&#8594; Mentor and Train</strong></h4><p>Share your expertise through mentoring and training.</p><h4><strong>&#8594; Encourage Collaboration</strong></h4><p>Foster a culture of regular knowledge sharing and collaboration.</p><h4><strong>&#8594; Implement Pair Programming</strong></h4><p>Don't ever underestimate the effectiveness of this method for spreading knowledge.</p><h4><strong>&#8594; Conduct Regular Reviews</strong></h4><p>Have team members explain various project aspects, highlighting knowledge gaps.</p><p>By sharing your knowledge, you enhance team resilience and equip them to face challenges.</p><p>Additionally, you help maintain a <strong>high bus factor</strong>, meaning a greater number of people would need to leave the team before the project is in jeopardy.</p><p>And don't mistakenly think this approach only benefits the team and the project. It also showcases your leadership qualities and commitment to collective growth.</p><p></p><h3><strong>Conclusion</strong></h3><p>Being indispensable might seem like job security. But in fact, it can hinder career progression.</p><p>Making yourself replaceable shows leadership, strengthens the team, and opens up personal growth opportunities.</p><p>Reducing the bus factor isn't just about protecting the project. It's about creating a dynamic, adaptable, and resilient work environment conducive to everyone's growth.</p><p></p><h4><strong>P.S.</strong></h4><p>I also read about a different, more positive analogy, used by Microsoft - <em><strong>the lottery analogy</strong></em>:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9nx8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad739ef2-c51a-4c31-b241-71dd763b080d_1111x228.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9nx8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad739ef2-c51a-4c31-b241-71dd763b080d_1111x228.png 424w, https://substackcdn.com/image/fetch/$s_!9nx8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad739ef2-c51a-4c31-b241-71dd763b080d_1111x228.png 848w, https://substackcdn.com/image/fetch/$s_!9nx8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad739ef2-c51a-4c31-b241-71dd763b080d_1111x228.png 1272w, https://substackcdn.com/image/fetch/$s_!9nx8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad739ef2-c51a-4c31-b241-71dd763b080d_1111x228.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9nx8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad739ef2-c51a-4c31-b241-71dd763b080d_1111x228.png" width="1111" height="228" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ad739ef2-c51a-4c31-b241-71dd763b080d_1111x228.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:228,&quot;width&quot;:1111,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:52483,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!9nx8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad739ef2-c51a-4c31-b241-71dd763b080d_1111x228.png 424w, https://substackcdn.com/image/fetch/$s_!9nx8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad739ef2-c51a-4c31-b241-71dd763b080d_1111x228.png 848w, https://substackcdn.com/image/fetch/$s_!9nx8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad739ef2-c51a-4c31-b241-71dd763b080d_1111x228.png 1272w, https://substackcdn.com/image/fetch/$s_!9nx8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad739ef2-c51a-4c31-b241-71dd763b080d_1111x228.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>However, while definitely less morbid, I don&#8217;t think it depicts the concept of multiple people leaving the team on a reasonable scale.</p><p></p><p>Do you and your team mitigate <strong>the bus factor?</strong></p><div><hr></div><p>P.S. If you liked this post, share it with your friends and colleagues.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/p/bus-factor-explained?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thesunshinelayer.com/p/bus-factor-explained?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Sunshine Layer! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Detroit vs London schools of unit testing]]></title><description><![CDATA[Are you a classicist or a mockist when it comes to unit testing?]]></description><link>https://www.thesunshinelayer.com/p/detroit-vs-london-schools-of-unit</link><guid isPermaLink="false">https://www.thesunshinelayer.com/p/detroit-vs-london-schools-of-unit</guid><dc:creator><![CDATA[Elena Sunshine]]></dc:creator><pubDate>Mon, 12 Feb 2024 05:30:25 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/6eac8e98-1d6f-474b-9ed4-e6965640df5f_4200x3000.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em><strong>Unit</strong></em><strong> tests</strong> are designed to verify a single <em>unit of behavior</em> in the most isolated condition possible. This isolation ensures that the test does not depend on any external factors and solely <strong>verifies the </strong><em><strong>unit</strong></em><strong>'s behavior.</strong></p><p>But <strong>what exactly is a </strong><em><strong>unit?</strong></em></p><p>The definition of a "unit" has been such a polarizing question, that it led to the formation of two schools of unit testing:</p><ul><li><p><strong>Detroit (Classicist) school</strong></p></li><li><p><strong>London (Mockist) school</strong></p></li></ul><p>So <em><strong>what&#8217;s the difference</strong></em>?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-5Y-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03a71ecb-a323-4f24-b1ab-765322bf9f77_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-5Y-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03a71ecb-a323-4f24-b1ab-765322bf9f77_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!-5Y-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03a71ecb-a323-4f24-b1ab-765322bf9f77_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!-5Y-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03a71ecb-a323-4f24-b1ab-765322bf9f77_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!-5Y-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03a71ecb-a323-4f24-b1ab-765322bf9f77_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-5Y-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03a71ecb-a323-4f24-b1ab-765322bf9f77_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/03a71ecb-a323-4f24-b1ab-765322bf9f77_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:313275,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-5Y-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03a71ecb-a323-4f24-b1ab-765322bf9f77_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!-5Y-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03a71ecb-a323-4f24-b1ab-765322bf9f77_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!-5Y-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03a71ecb-a323-4f24-b1ab-765322bf9f77_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!-5Y-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03a71ecb-a323-4f24-b1ab-765322bf9f77_2380x2380.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The <strong>Detroit school (classicist)</strong> argues that</p><ul><li><p><em><strong>Unit tests themselves need to be isolated</strong></em>, not necessarily the units.</p></li><li><p><em>A unit under test is more about a unit of behavior</em>, rather than just code.</p></li><li><p><em>Only <strong>shared</strong> dependencies</em> (those which can make tests affect each other) <em>should be replaced with test doubles</em>.</p></li></ul><p>The <strong>London school (Mockist)</strong> believes that</p><ul><li><p><em>Units under test</em> (often classes) should be <em><strong>isolated from each other</strong></em>.</p></li><li><p><em><strong>All</strong> dependencies</em> should be <em>replaced with test doubles</em> (like mocks or stubs) in tests (except for immutable dependencies).</p></li></ul><h2>Deep-dive comparison</h2><h3><strong>Classicist (Detroit School)</strong></h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!y7d8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06f9247-22d7-42fc-8bbf-8763f3ead8d0_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!y7d8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06f9247-22d7-42fc-8bbf-8763f3ead8d0_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!y7d8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06f9247-22d7-42fc-8bbf-8763f3ead8d0_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!y7d8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06f9247-22d7-42fc-8bbf-8763f3ead8d0_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!y7d8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06f9247-22d7-42fc-8bbf-8763f3ead8d0_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!y7d8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06f9247-22d7-42fc-8bbf-8763f3ead8d0_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d06f9247-22d7-42fc-8bbf-8763f3ead8d0_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:527358,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!y7d8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06f9247-22d7-42fc-8bbf-8763f3ead8d0_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!y7d8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06f9247-22d7-42fc-8bbf-8763f3ead8d0_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!y7d8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06f9247-22d7-42fc-8bbf-8763f3ead8d0_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!y7d8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06f9247-22d7-42fc-8bbf-8763f3ead8d0_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><ul><li><p><strong>State-Based Testing</strong></p><p>Focuses on the state of the application after a unit's execution, verifying outcomes based on the input and the final state.</p><p>This approach is <em><strong>less about how the result is achieved and more about ensuring the end state is correct</strong></em>.</p></li><li><p><strong>Integration of Collaborators</strong></p><p>Rather than mocking dependencies, favors using real instances of objects or in-memory test doubles, aiming to test units in a context that closely mirrors how they operate within the full application.</p><p>This can lead to tests that are more integrative and less isolated.</p></li><li><p><strong>Refactoring Flexibility</strong></p><p>A hallmark of the Classicist approach is its emphasis on refactoring.</p><p>Since tests are not tightly coupled to the implementation details, developers can refactor code with confidence as long as the external behavior remains unchanged.</p></li><li><p><strong>Critiques of Mocking</strong></p><p>Detroit school argues that excessive mocking can lead to brittle tests that are overly tied to the implementation details, potentially leading to false positives and hindering refactoring efforts.</p></li></ul><h3><strong>Mockist (London School)</strong></h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1rZn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8188c85-55b5-4a1b-873a-a0f2b44501f7_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1rZn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8188c85-55b5-4a1b-873a-a0f2b44501f7_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!1rZn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8188c85-55b5-4a1b-873a-a0f2b44501f7_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!1rZn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8188c85-55b5-4a1b-873a-a0f2b44501f7_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!1rZn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8188c85-55b5-4a1b-873a-a0f2b44501f7_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1rZn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8188c85-55b5-4a1b-873a-a0f2b44501f7_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d8188c85-55b5-4a1b-873a-a0f2b44501f7_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:467955,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1rZn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8188c85-55b5-4a1b-873a-a0f2b44501f7_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!1rZn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8188c85-55b5-4a1b-873a-a0f2b44501f7_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!1rZn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8188c85-55b5-4a1b-873a-a0f2b44501f7_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!1rZn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8188c85-55b5-4a1b-873a-a0f2b44501f7_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><ul><li><p><strong>Interaction-Based Testing</strong></p><p>Prioritizes testing every class interaction meticulously, using mocks extensively to ensure that objects communicate correctly with their dependencies.</p><p>This approach focuses on the pathways through the code rather than the final state.</p></li><li><p><strong>Isolation</strong></p><p>By mocking dependencies, it aims to isolate the unit under test, ensuring that failures are localized to the unit itself rather than being influenced by external factors or the behavior of dependencies.</p></li><li><p><strong>Behavior Verification</strong></p><p>Tests in the Mockist approach often verify that certain methods are called with the expected arguments, <em><strong>emphasizing the behavior over the state</strong></em>.</p><p>This can make the tests <em><strong>more sensitive to changes in the code's structure.</strong></em></p></li><li><p><strong>Refactoring Constraints</strong></p><p>While Mockist tests can be very precise in ensuring correct interactions, they can also become tightly coupled to the code's structure, making refactoring more challenging without breaking tests.</p><p>This is a significant critique of the approach, as it may limit the ability to evolve the codebase.</p></li><li><p><strong>Simplicity in Mocked Behavior</strong></p><p>Mocks are designed to be as simple as possible, only providing the minimum required to make a test pass, which can lead to a mismatch if the behavior of the class changes but the mocks in other classes' tests are not updated.</p></li><li><p><strong>Increased Interfaces for Mocking</strong></p><p>May result in more interfaces in production code to facilitate mocking, tying tests closely to the code's architecture and potentially increasing the refactoring or rework cost.</p></li><li><p><strong>Maintenance Cost</strong></p><p>High, particularly if classes are tightly coupled. The approach promotes projects with loosely coupled, independent classes to keep maintenance manageable.</p></li></ul><h2><strong>Choosing Between the Schools</strong></h2><ul><li><p><strong>London School for Libraries:</strong> Well-suited for library development where classes are loosely coupled, and the behavior of public APIs needs clear definition and stability.</p><p>The low maintenance cost and ease of use of mocks make it an attractive choice for ensuring API behavior contracts.</p></li><li><p><strong>Detroit School for Applications and Microservices:</strong> Ideal for applications where business objectives dictate rapid responsiveness to change. The emphasis on comprehensive behavior verification and less frequent need to alter test code in response to production code refactoring makes it suitable for projects with dynamic requirements.</p></li></ul><h3><strong>Balancing Trade-offs</strong></h3><ul><li><p><strong>False Positives and Refactoring:</strong> Mockist approaches may lead to higher instances of false positives in tests, where tests fail not due to bugs but due to changes in the implementation details. This can slow down development and make the test suite harder to maintain.</p></li><li><p><strong>Black Box vs. White Box Testing:</strong> The Classicist approach aligns with black box testing, focusing on the inputs and outputs without regard to internal workings. In contrast, the Mockist approach is akin to white box testing, with a deep understanding of the internal pathways of the code being necessary to write effective tests.</p></li><li><p><strong>Debugging and Design Freedom:</strong> Mockist testing can offer more granular insights during debugging but may restrict design flexibility due to its prescriptive nature. The Classicist approach, while less granular, offers more design freedom and facilitates easier refactoring.</p></li></ul><p>Ultimately, the decision between these schools should be guided by the project's specific requirements and the development team's preferences. A hybrid approach might even be the most effective in certain contexts, leveraging the strengths of both methodologies:</p><ul><li><p><strong>Combining Approaches for Comprehensive Testing</strong></p><p>Use Mockist techniques for unit testing individual components and Classicist strategies for integration and system tests to ensure overall behavior correctness.</p></li><li><p><strong>Evolving Strategies Over Time</strong></p><p>Start with a Mockist approach in the early stages of development when interfaces are more volatile, and transition to Classicist methods as the software stabilizes.</p></li></ul><h2><strong>Conclusion</strong></h2><p>The debate between Classicist and Mockist approaches in TDD is not about which is universally better but about understanding the trade-offs and advantages of both.</p><p>What each school calls "units" should not merely represent units of code but units of behavior &#8212; actions or sequences that are meaningful within the problem domain and recognizable as valuable by stakeholders, including those in business roles.</p><p>The significance of a unit lies not in its size or the number of classes it encompasses but in its relevance and utility in solving a real-world problem.</p><p>Whether a behavior spans multiple classes, a single class, or merely a fraction of a method, the focus remains on its purpose and contribution to the application's overall functionality.</p><p>The key is not to adhere rigidly to one school but to understand the benefits and limitations of each approach and pragmatically use them based on the specific needs of the project.</p><div><hr></div><p>P.S. If you enjoyed this post, share it with your friends and colleagues.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/p/detroit-vs-london-schools-of-unit?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thesunshinelayer.com/p/detroit-vs-london-schools-of-unit?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Sunshine Layer! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Richardson Maturity Model]]></title><description><![CDATA[A roadmap for your API development from the basics of request-response to the holy grail of HATEOAS.]]></description><link>https://www.thesunshinelayer.com/p/richardson-maturity-model</link><guid isPermaLink="false">https://www.thesunshinelayer.com/p/richardson-maturity-model</guid><dc:creator><![CDATA[Elena Sunshine]]></dc:creator><pubDate>Mon, 05 Feb 2024 06:00:56 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/f8a34776-06b8-4778-bad9-5930ea8fc7ec_4200x3000.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ever wondered why some APIs feel like a dream to work with, while others feel like navigating a labyrinth?</p><p>What if I told you that the difference between an API that's merely good and one that's truly great could be measured?</p><p>Richardson Maturity Model is a measure used to gauge the maturity of a RESTful API.</p><p>This model, proposed by Leonard Richardson, is divided into <strong>four levels</strong>, from Level 0 to Level 3, with each level introducing more sophisticated RESTful principles, culminating in the concept of HATEOAS (Hypermedia as the Engine of Application State).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!E3Vn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c4f9b2f-666d-4718-910f-9a4b79c0e912_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!E3Vn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c4f9b2f-666d-4718-910f-9a4b79c0e912_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!E3Vn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c4f9b2f-666d-4718-910f-9a4b79c0e912_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!E3Vn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c4f9b2f-666d-4718-910f-9a4b79c0e912_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!E3Vn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c4f9b2f-666d-4718-910f-9a4b79c0e912_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!E3Vn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c4f9b2f-666d-4718-910f-9a4b79c0e912_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5c4f9b2f-666d-4718-910f-9a4b79c0e912_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:316534,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!E3Vn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c4f9b2f-666d-4718-910f-9a4b79c0e912_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!E3Vn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c4f9b2f-666d-4718-910f-9a4b79c0e912_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!E3Vn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c4f9b2f-666d-4718-910f-9a4b79c0e912_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!E3Vn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c4f9b2f-666d-4718-910f-9a4b79c0e912_2380x2380.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Let's go through RMM using the example of an online bookstore system.</p><p>I will illustrate how the system's web service evolves from Level 0 to Level 3, showcasing the benefits and changes at each stage.</p><h3><strong>Level 0: The Swamp of POX</strong></h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LEar!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe933d421-3713-4b06-875f-77fbd70271ab_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LEar!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe933d421-3713-4b06-875f-77fbd70271ab_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!LEar!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe933d421-3713-4b06-875f-77fbd70271ab_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!LEar!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe933d421-3713-4b06-875f-77fbd70271ab_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!LEar!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe933d421-3713-4b06-875f-77fbd70271ab_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LEar!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe933d421-3713-4b06-875f-77fbd70271ab_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e933d421-3713-4b06-875f-77fbd70271ab_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:274091,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!LEar!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe933d421-3713-4b06-875f-77fbd70271ab_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!LEar!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe933d421-3713-4b06-875f-77fbd70271ab_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!LEar!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe933d421-3713-4b06-875f-77fbd70271ab_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!LEar!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe933d421-3713-4b06-875f-77fbd70271ab_2380x2380.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>At Level 0, the online bookstore API does not adhere to REST principles.</p><p>It has <strong>a single entry point for all interactions</strong>, such as fetching book information, placing an order, or updating user profiles. Clients communicate with the service using only POST requests.</p><p>There's no standard mechanism to manage state or leverage HTTP's built-in capabilities.</p><p>This level is characterized by its simplicity but also its limited use of HTTP's potential and is reminiscent of SOAP-based services.</p><p>Such APIs are still found in legacy systems where changing architectural styles would require significant refactoring.</p><p>However, for new developments, you should avoid it in favor of more RESTful approaches.</p><p></p><h2><strong>Level 1: Resources</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sPWT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe36f8df3-337f-4084-8031-bb6587ea755a_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sPWT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe36f8df3-337f-4084-8031-bb6587ea755a_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!sPWT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe36f8df3-337f-4084-8031-bb6587ea755a_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!sPWT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe36f8df3-337f-4084-8031-bb6587ea755a_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!sPWT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe36f8df3-337f-4084-8031-bb6587ea755a_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!sPWT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe36f8df3-337f-4084-8031-bb6587ea755a_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e36f8df3-337f-4084-8031-bb6587ea755a_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:322976,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!sPWT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe36f8df3-337f-4084-8031-bb6587ea755a_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!sPWT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe36f8df3-337f-4084-8031-bb6587ea755a_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!sPWT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe36f8df3-337f-4084-8031-bb6587ea755a_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!sPWT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe36f8df3-337f-4084-8031-bb6587ea755a_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This level introduces the concept of <strong>individual resources</strong>.</p><p>The bookstore service starts to differentiate between types of resources by assigning them unique URIs. For instance, individual books, users, and orders each get their own URI.</p><p><strong>To get information about a book, a client now sends a GET request to a specific book URI.</strong></p><p>The response structure remains similar but is accessed through a more specific, resource-oriented URL.</p><p>This marks a significant step towards RESTful design by recognizing that different data entities should have separate URIs.</p><p>Level 1 is widely adopted as the minimum standard for web APIs.</p><p>It simplifies the design by allowing direct access to specific resources but does not leverage the full power of HTTP.</p><p><strong>The resources should be plural nouns. Using verbs in URI is bad practice.</strong></p><p></p><h2><strong>Level 2: HTTP Verbs</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!itrG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9813461-4f78-434c-b947-b454336128e8_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!itrG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9813461-4f78-434c-b947-b454336128e8_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!itrG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9813461-4f78-434c-b947-b454336128e8_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!itrG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9813461-4f78-434c-b947-b454336128e8_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!itrG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9813461-4f78-434c-b947-b454336128e8_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!itrG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9813461-4f78-434c-b947-b454336128e8_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a9813461-4f78-434c-b947-b454336128e8_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:460366,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!itrG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9813461-4f78-434c-b947-b454336128e8_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!itrG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9813461-4f78-434c-b947-b454336128e8_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!itrG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9813461-4f78-434c-b947-b454336128e8_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!itrG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9813461-4f78-434c-b947-b454336128e8_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>At Level 2, the bookstore service begins to utilize HTTP verbs appropriately to define actions on resources.</p><p>This aligns the actions with the type of request being made, such as GET for retrieval, POST for creation, PUT for updates, and DELETE for deletions.</p><p><strong>To place a new order, a client now uses POST to an orders resource, with a payload specifying the order details, such as the book ID and quantity.</strong></p><p><strong>To update a book, a client uses PUT, specifying the book ID and providing the new data.</strong></p><p>This not only adheres to the principles of REST, but also enhances semantic clarity and the potential for caching.</p><p>Level 2 is considered a best practice for RESTful API design. It's commonly seen in web services, offering a balance between simplicity and the expressive power of HTTP.</p><p></p><h2><strong>Level 3: Hypermedia Controls (HATEOAS)</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IPTa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01727673-85d4-4ca5-917b-ad03a18f3ae8_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IPTa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01727673-85d4-4ca5-917b-ad03a18f3ae8_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!IPTa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01727673-85d4-4ca5-917b-ad03a18f3ae8_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!IPTa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01727673-85d4-4ca5-917b-ad03a18f3ae8_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!IPTa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01727673-85d4-4ca5-917b-ad03a18f3ae8_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IPTa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01727673-85d4-4ca5-917b-ad03a18f3ae8_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/01727673-85d4-4ca5-917b-ad03a18f3ae8_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:335514,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IPTa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01727673-85d4-4ca5-917b-ad03a18f3ae8_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!IPTa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01727673-85d4-4ca5-917b-ad03a18f3ae8_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!IPTa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01727673-85d4-4ca5-917b-ad03a18f3ae8_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!IPTa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01727673-85d4-4ca5-917b-ad03a18f3ae8_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The highest maturity level introduces Hypermedia as the Engine of Application State (HATEOAS). At this stage, responses include hypermedia controls, guiding clients on potential actions through links within the response, making the API self-descriptive and fully navigable.</p><p><strong>A response not only includes details about the book but also links for actions such as placing an order.</strong></p><p>Despite its benefits, Level 3 has been slower to gain widespread adoption.</p><p>Challenges include increased complexity in client implementation and a lack of tooling support.</p><p>However, it's seen as the gold standard for RESTful design, promoting loose coupling and evolvability.</p><p>Strong APIs that require a high degree of discoverability and flexibility implement HATEOAS principles.</p><p></p><h2>10 Questions &amp; Considerations:</h2><h3>1. REST, RESTful or REST HATEOAS?</h3><ul><li><p><strong>REST</strong> is the architectural style underlying the web, focusing on stateless communication, resource identification, and the use of standard HTTP methods.</p></li><li><p><strong>RESTful</strong> APIs are those that adhere to REST principles, aiming for a stateless, cacheable, and layered system with uniform interfaces.</p></li><li><p><strong>HATEOAS</strong> (Hypermedia as the Engine of Application State) is a component of RESTful APIs, requiring responses to include hyperlinks to other actions and resources, allowing for dynamic client navigation and coincides with Level 3 of RMM.</p></li></ul><h3><strong>2. What Are the Purposes of Different HTTP Verbs?</strong></h3><p>Understanding the purpose of HTTP verbs and their proper use is crucial in designing RESTful APIs and ensuring they are both intuitive and adhere to web standards. Here's a detailed look at the key HTTP methods, their intended actions, and guidance on some common edge cases.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6-0I!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e7799c-5ed7-44cd-8aee-c2a900d2f06f_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6-0I!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e7799c-5ed7-44cd-8aee-c2a900d2f06f_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!6-0I!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e7799c-5ed7-44cd-8aee-c2a900d2f06f_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!6-0I!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e7799c-5ed7-44cd-8aee-c2a900d2f06f_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!6-0I!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e7799c-5ed7-44cd-8aee-c2a900d2f06f_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6-0I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e7799c-5ed7-44cd-8aee-c2a900d2f06f_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/15e7799c-5ed7-44cd-8aee-c2a900d2f06f_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:409072,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6-0I!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e7799c-5ed7-44cd-8aee-c2a900d2f06f_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!6-0I!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e7799c-5ed7-44cd-8aee-c2a900d2f06f_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!6-0I!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e7799c-5ed7-44cd-8aee-c2a900d2f06f_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!6-0I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15e7799c-5ed7-44cd-8aee-c2a900d2f06f_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h4><strong>GET</strong></h4><p><strong>Purpose:</strong> Retrieve data from a server at the specified resource. GET requests should be idempotent, meaning multiple identical requests should have the same effect as a single one.</p><p><strong>Actions:</strong> Used to request data without causing any side effects. This is the method used for searching or querying resources with specific parameters.</p><h4><strong>HEAD</strong></h4><p><strong>Purpose:</strong> The HEAD method is used to retrieve the headers of a resource, without the body. It's essentially a GET request without the response body. This is useful for checking what a GET request will return in terms of headers, status code, or to verify if a resource exists before downloading it.</p><p><strong>Actions:</strong> Used to check if a resource exists. It can verify if there have been modifications to a resource (using headers like <code>Last-Modified</code> or <code>ETag</code>). Can also check the size of a resource before downloading it, via the <code>Content-Length</code> header.</p><h4><strong>POST</strong></h4><p><strong>Purpose:</strong> Submit data to the server to create or update a resource, or trigger a non-idempotent operation. <strong>It</strong> <strong>does not require the client to know the resource's URI beforehand</strong>.</p><p><strong>Actions:</strong> Used for creating new resources, submitting form data, or triggering operations that change the server's state.</p><h4><strong>PUT</strong></h4><p><strong>Purpose:</strong> Replace the target resource with the request payload.</p><p>It is idempotent, meaning subsequent identical requests should ensure the same state on the server.</p><p><strong>Actions:</strong> Typically <strong>used for updating existing resources</strong> in their entirety or creating a resource at a specific URL if it doesn't exist.</p><h4><strong>PATCH</strong></h4><p><strong>Purpose:</strong> Apply a partial update to a resource. Like PUT, it is intended for modifying resources but only changes the parts specified in the request.</p><p><strong>Actions:</strong> Ideal for <strong>updating only a subset of a resource's data</strong>, making it more efficient than PUT for large resources with minor changes.</p><h4><strong>DELETE</strong></h4><p><strong>Purpose:</strong> Remove the specified resource from the server.</p><p><strong>Actions:</strong> Used to <strong>permanently delete a resource.</strong> It is idempotent, as the resource remains deleted after multiple identical requests.</p><h4><strong>OPTIONS</strong></h4><p><strong>Purpose:</strong> Describes the communication options for the target resource. It's used to discover which HTTP methods are supported by a web server for a given resource. This can be particularly useful in RESTful APIs for supporting cross-origin resource sharing (CORS) preflight requests.</p><p><strong>Actions:</strong> Used to determine the HTTP methods (GET, POST, PUT, PATCH, DELETE, etc.) that a server supports for a specific URL. Can check for CORS policies by revealing allowed origins, HTTP methods, and headers. It&#8217;s also useful in assisting in the exploration and debugging of APIs by providing information about how to interact with a resource.</p><h3>3. Are HTTP Methods Idempotent?</h3><p>GET, HEAD, PUT, DELETE and OPTIONS are considered idempotent, meaning repeating the requests multiple times has the same effect as making a single request.</p><p>POST is not idempotent, as repeating a POST request can create multiple resources or trigger the operation multiple times. Patch can be idempotent, but it&#8217;s not a guarantee.</p><h3><strong>4. Can GET Requests Have Bodies? Should They?</strong></h3><p>While technically possible, GET requests with bodies are not recommended and widely unsupported, as most servers ignore it.</p><p>It's not standard practice to send a body with GET requests, and doing so can lead to unpredictable behavior.</p><p>GET requests should <strong>convey requests via URI and query parameters</strong>, adhering to the HTTP specification and ensuring compatibility and predictability across web services.</p><p>This allows filtering or paging resources without changing the server's state, hence maintaining idempotency.</p><p>For complex queries that do not fit well within a URL's query parameters, a POST request to a search endpoint might be more appropriate, despite traditionally being a GET operation. <strong>This is an exception rather than the rule.</strong></p><h3><strong>5. Is a soft delete a HTTP DELETE or not?</strong></h3><p>Soft deletes can be a DELETE request that, instead of removing the resource, marks it as inactive. Alternatively, a PATCH to update a status could be more semantically correct, depending on the implementation. Here consistency and team agreements come into play.</p><h3><strong>6. What Are HTTP Status Codes?</strong></h3><p>HTTP status codes are standardized codes in the Hypertext Transfer Protocol (HTTP) used by web servers to indicate the status of a request's response. These codes are part of the response message from the server and help the client understand the result of their request. They are grouped into five categories, each signifying a different type of response:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!utIj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a6f091-5b84-4de4-9e21-33d9eab8ece0_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!utIj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a6f091-5b84-4de4-9e21-33d9eab8ece0_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!utIj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a6f091-5b84-4de4-9e21-33d9eab8ece0_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!utIj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a6f091-5b84-4de4-9e21-33d9eab8ece0_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!utIj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a6f091-5b84-4de4-9e21-33d9eab8ece0_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!utIj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a6f091-5b84-4de4-9e21-33d9eab8ece0_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/63a6f091-5b84-4de4-9e21-33d9eab8ece0_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:532409,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!utIj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a6f091-5b84-4de4-9e21-33d9eab8ece0_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!utIj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a6f091-5b84-4de4-9e21-33d9eab8ece0_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!utIj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a6f091-5b84-4de4-9e21-33d9eab8ece0_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!utIj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a6f091-5b84-4de4-9e21-33d9eab8ece0_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><ol><li><p><strong>1xx (Informational):</strong> Indicates provisional responses, requiring the requester to initiate a follow-up request to receive the final response.</p></li><li><p><strong>2xx (Success):</strong> Signals that the request was successfully received, understood, and accepted.</p></li><li><p><strong>3xx (Redirection):</strong> Means further action needs to be taken by the user agent to fulfill the request, typically a redirection to another URI.</p></li><li><p><strong>4xx (Client Error):</strong> Indicates an error on the client's part, such as a bad request or unauthorized access.</p></li><li><p><strong>5xx (Server Error):</strong> Signifies an error on the server's part, indicating the server failed to fulfill a valid request.</p></li></ol><p>Each category has various specific codes, such as <code>200 OK</code> for a successful request, <code>404 Not Found</code> when a resource can't be located, or <code>500 Internal Server Error</code> for general server failures.</p><h3><strong>7. How to Use HTTP Status Codes?</strong></h3><p>They are used to communicate the outcome of HTTP requests.</p><p>Clients, such as web browsers or API consumers, use these codes to determine the next steps in their process.</p><p>For example, a <code>200 OK</code> status may lead to the display of content to a user, while a <code>401 Unauthorized</code> status could trigger a login flow. They are essential for RESTful API design, providing a standardized method for indicating success, failure, and required actions to clients.</p><h3><strong>8. Should I Use Status Codes for Business Validation?</strong></h3><p>HTTP status codes are well-suited for indicating the technical outcome of a request (e.g., whether or not it was successfully processed by the server).</p><p>Sometimes they can also be used to some extent for business logic errors, provided there's a good match between the status code semantics and the business error condition. For common business validation errors, such as input data failing validation checks, <code>400 Bad Request</code> is appropriate.</p><p>However, it's important not to stretch the semantics of HTTP status codes too far to fit business logic errors. Because in most of the cases, you need more than that.</p><p>So what do you do, return <code>200 OK</code> with a Business Error in the Response body?</p><p>The best of both worlds is returning a general status code like <code>400 Bad Request</code> or <code>422 Unprocessable Entity</code> (for semantic errors in the request) and include a detailed error message in the response body.</p><p>This approach allows you to communicate specific business rule failures or validation messages in a structured format that clients can parse and handle accordingly.</p><h3><strong>9. Should Hypermedia Include Links to All Possible Endpoints?</strong></h3><p>Hypermedia does not necessarily mean exposing all possible endpoints directly, but providing a way to navigate the API dynamically.</p><p>It's about providing relevant links and actions based on the current resource state or context, thus maintaining a balance between discoverability and security.</p><p>For instance, a user resource might include links to related resources like a user's posts or profile settings, rather than exposing unrelated endpoints.</p><p>This approach reduces coupling and improves discoverability without necessarily exposing the full API surface.</p><h3><strong>10. How Does Versioning Fit in?</strong></h3><p>Versioning APIs is a critical aspect of designing and maintaining web services, ensuring that they can evolve over time without disrupting existing clients.</p><p>Versioning within RMM should be handled in a way that maintains the API's RESTful nature.</p><p>Techniques like using HTTP headers for version information or leveraging content negotiation allow the APIs to introduce versions without breaking HATEOAS principles or cluttering URIs with version numbers.</p><p></p><p>The Richardson Maturity Model provides a structured path towards fully RESTful services, emphasizing the importance of using HTTP verbs appropriately, considering hypermedia's role in API design, and integrating versioning thoughtfully.</p><p>By understanding and applying these principles, you can create more robust, scalable, and maintainable web services that offer greater flexibility and user experience.</p><div><hr></div><p>P.S. If you enjoyed this post, share it with your friends and colleagues.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/p/richardson-maturity-model?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thesunshinelayer.com/p/richardson-maturity-model?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Sunshine Layer! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[The PH of a Database]]></title><description><![CDATA[ACID vs BASE: Foundational Principles for Database Transaction Management]]></description><link>https://www.thesunshinelayer.com/p/the-ph-of-a-database</link><guid isPermaLink="false">https://www.thesunshinelayer.com/p/the-ph-of-a-database</guid><dc:creator><![CDATA[Elena Sunshine]]></dc:creator><pubDate>Sat, 27 Jan 2024 16:15:53 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/158e052e-50bd-4b38-8d05-23c45ac0a932_4200x3000.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Whenever we consider what database to choose for our project, we need to factor in how data integrity and consistency needs to be maintained.</p><p><strong>ACID</strong> and <strong>BASE</strong> are two models that describe different approaches and guarantees in handling transactions and data consistency. Understanding these concepts is key to selecting the right approach for database design and choosing the right type of database system for your specific application needs.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JeBW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5967f082-5dc1-4b1a-a426-8d4145aeaf5e_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JeBW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5967f082-5dc1-4b1a-a426-8d4145aeaf5e_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!JeBW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5967f082-5dc1-4b1a-a426-8d4145aeaf5e_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!JeBW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5967f082-5dc1-4b1a-a426-8d4145aeaf5e_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!JeBW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5967f082-5dc1-4b1a-a426-8d4145aeaf5e_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!JeBW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5967f082-5dc1-4b1a-a426-8d4145aeaf5e_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5967f082-5dc1-4b1a-a426-8d4145aeaf5e_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:380398,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!JeBW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5967f082-5dc1-4b1a-a426-8d4145aeaf5e_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!JeBW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5967f082-5dc1-4b1a-a426-8d4145aeaf5e_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!JeBW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5967f082-5dc1-4b1a-a426-8d4145aeaf5e_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!JeBW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5967f082-5dc1-4b1a-a426-8d4145aeaf5e_2380x2380.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong>ACID Model</strong></h2><p>Traditionally associated with relational databases (RDBMS), ACID is a standard for ensuring reliable transaction processing.</p><p>The pillars of the ACID are:</p><h4><strong>&#8594; Atomicity</strong></h4><h4><strong>&#8594; Consistency</strong></h4><h4><strong>&#8594; Isolation</strong></h4><h4><strong>&#8594; Durability</strong></h4><p>These four principles are not just theoretical concepts. They are the crucial foundations that ensure transaction reliability and integrity in every database.</p><p>Let's break these down like we would in a real-world project:</p><h3><strong>&#8594; Atomicity</strong></h3><p>Think of this as an all-or-nothing approach. When you commit a transaction, either the whole thing goes through, or none of it does. It's like a team effort in a code sprint &#8212; if one part fails, the whole thing needs a rethink.</p><h3><strong>&#8594; Consistency</strong></h3><p>This is your quality control. It ensures that every transaction transforms your database from one valid state to another, never breaking the rules you've set.</p><h3><strong>&#8594; Isolation</strong></h3><p>Here's where things get tricky with concurrent transactions. Isolation means keeping these transactions independent of each other. It's like making sure your threads don't step on each other's toes.</p><h3><strong>&#8594; Durability</strong></h3><p>Once your transaction commits, it's set in stone, even if a system failure occurs immediately after. This is your safety net, ensuring that what's done stays done.</p><h3><strong>Use Case</strong></h3><p>Ideal for systems where data integrity and consistency are non-negotiable, such as banking and financial systems.</p><h2><strong>BASE Model</strong></h2><p>BASE is often used in the context of distributed databases, particularly NoSQL databases, where achieving high availability and scalability is more critical than strict consistency. It is in sharp contrast with the traditional ACID (Atomicity, Consistency, Isolation, Durability) model of relational databases.</p><p>BASE acronym stands for:</p><h4><strong>&#8594; Basically Available</strong></h4><h4><strong>&#8594; Soft state</strong></h4><h4><strong>&#8594; Eventual consistency</strong></h4><p>Let&#8217;s break down what BASE means and how it shapes the behavior and design of NoSQL systems.</p><h3><strong>&#8594; Basically Available</strong></h3><p>We're talking <em><strong>Availability over Consistency</strong>.</em></p><p>NoSQL databases prioritize availability. The system aims to ensure that the database is available for read and write operations, even in the face of network failures or partitioning.</p><p>This leads to <em><strong>flexible downtime handling.</strong></em> While the system might not be 100% consistent at all times (unlike ACID systems), it ensures that basic operations can still be performed, albeit with some flexibility in terms of consistency.</p><h3><strong>&#8594; Soft state</strong></h3><p>This translates to having <em><strong>state flexibility.</strong></em> The state of the database is "soft", implying that it can change over time, even without input. It is a departure from the rigid, stable state maintained in ACID databases.</p><p>It also implies having some <em><strong>tolerance to change.</strong></em> This aspect of BASE acknowledges that the database doesn&#8217;t always have to be perfectly consistent. Instead, it can tolerate some amount of temporary inconsistency or latency.</p><h3><strong>&#8594; Eventually consistent</strong></h3><p>The system needs to assume some <em><strong>delayed consistency</strong></em>. Eventually, the database will become consistent. However, this consistency is not guaranteed at all times, especially immediately following write operations.</p><p>System experiences a <em><strong>real-world sync</strong></em>.</p><p>Think of it like updates propagating across various social media servers. While some users might see the latest content immediately, others might see it after a short delay.</p><h3><strong>Impact of BASE in NoSQL</strong></h3><p>The system has high <em><strong>scalability and performance</strong></em>. By relaxing the constraints on consistency, NoSQL databases designed with the BASE model can achieve higher levels of scalability and performance, particularly beneficial for large-scale, distributed systems.</p><h3><strong>Use Cases</strong></h3><p>The ideal candidates are applications where <strong>availability</strong> and <strong>partition tolerance</strong> are critical. But where it's also <strong>acceptable for data to be slightly out of date or inconsistent temporarily</strong>. Think caching systems, user-facing applications with high traffic like social networks or e-commerce platforms and distributed applications.</p><h2><strong>ACID vs BASE: A Comparison</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!X2pN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe38cdec1-b46e-46b8-aa25-2be9ebc09a0c_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!X2pN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe38cdec1-b46e-46b8-aa25-2be9ebc09a0c_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!X2pN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe38cdec1-b46e-46b8-aa25-2be9ebc09a0c_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!X2pN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe38cdec1-b46e-46b8-aa25-2be9ebc09a0c_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!X2pN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe38cdec1-b46e-46b8-aa25-2be9ebc09a0c_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!X2pN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe38cdec1-b46e-46b8-aa25-2be9ebc09a0c_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e38cdec1-b46e-46b8-aa25-2be9ebc09a0c_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:494117,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!X2pN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe38cdec1-b46e-46b8-aa25-2be9ebc09a0c_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!X2pN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe38cdec1-b46e-46b8-aa25-2be9ebc09a0c_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!X2pN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe38cdec1-b46e-46b8-aa25-2be9ebc09a0c_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!X2pN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe38cdec1-b46e-46b8-aa25-2be9ebc09a0c_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><ol><li><p><strong>Consistency and Availability</strong>:</p><ul><li><p><strong>ACID:</strong> Prioritizes consistency.</p></li><li><p><strong>BASE:</strong> Prioritizes availability.</p></li></ul></li><li><p><strong>Flexibility:</strong></p><ul><li><p><strong>ACID:</strong> Offers less flexibility. It maintains immediate consistency, which may restrict access during network or power outages. Transactions queue up, causing delays.</p></li><li><p><strong>BASE:</strong> More flexible. Allows applications to modify records more freely, without strict queuing or waiting.</p></li></ul></li><li><p><strong>Performance:</strong></p><ul><li><p><strong>ACID:</strong> The overhead of maintaining strict consistency, isolation, and durability can impact performance, especially in high-load scenarios or distributed environments.</p></li><li><p><strong>BASE:</strong> By relaxing consistency requirements, BASE databases can offer better performance, particularly in distributed systems where latency and network overhead can be a factor.</p></li></ul></li><li><p><strong>Scale:</strong></p><ul><li><p><strong>ACID:</strong> Traditionally, ACID-compliant databases are optimized for reliability over scale. <strong>Scaling vertically</strong> (adding more resources to a single server) is common, but horizontal scaling (across multiple servers) can be challenging due to the strict consistency requirements.</p></li><li><p><strong>BASE:</strong> Designed with distributed systems in mind, BASE databases excel at <strong>horizontal scaling</strong>. They can handle large volumes of data across multiple servers, making them suitable for big data applications and cloud computing.</p></li></ul></li><li><p><strong>Synchronization:</strong></p><ul><li><p><strong>ACID:</strong> Requires tight synchronization to maintain consistency across transactions. This can lead to bottlenecks in distributed environments.</p></li><li><p><strong>BASE:</strong> Allows for more loose synchronization, leveraging eventual consistency. This approach reduces bottlenecks but may lead to temporary data inconsistencies.</p></li></ul></li><li><p><strong>System Design:</strong></p><ul><li><p><strong>ACID:</strong> ACID transactions are less flexible in terms of schema and data model changes. The rigid structure ensures data consistency but can limit adaptability to evolving data requirements.</p></li><li><p><strong>BASE:</strong> Offers greater flexibility in handling dynamic and evolving data models, often found in NoSQL databases. This is particularly useful in applications where the data schema may change over time.</p></li></ul></li></ol><h2>When to use each</h2><h3><strong>When to Use ACID</strong></h3><p>ACID databases are best suited for applications where data integrity and consistency are paramount. These include:</p><ul><li><p><strong>Financial Systems:</strong> Banks and financial institutions rely on ACID databases for processing transactions where accuracy and consistency of data are critical.</p></li><li><p><strong>E-Commerce Transactions:</strong> For handling purchases, order processing, and inventory management, where each transaction needs to be reliably recorded.</p></li><li><p><strong>Healthcare Systems:</strong> Patient records and medical transactions require strict data accuracy and consistency.</p></li><li><p><strong>Enterprise Applications:</strong> Many business applications require reliable transaction processing to maintain data integrity in operations like payroll, human resources, and supply chain management.</p></li></ul><p>In these cases, the potential performance trade-offs are acceptable given the necessity for strict consistency and reliability.</p><h3><strong>When to Use BASE</strong></h3><p>BASE databases are well-suited for applications where scalability and high availability are more important than strict consistency. These include:</p><ul><li><p><strong>Big Data Analytics:</strong> Applications dealing with large volumes of data where the focus is on analysis and reporting rather than transactional integrity.</p></li><li><p><strong>Social Networks:</strong> Handling a massive, distributed set of data where real-time data consistency is not as critical as availability and scalability.</p></li><li><p><strong>E-Commerce Product Catalogs:</strong> For managing dynamic information like product listings and prices, where eventual consistency is acceptable.</p></li><li><p><strong>Content Management Systems:</strong> Where high traffic demands scalability and the data (like comments, posts, etc.) can tolerate some degree of eventual consistency.</p></li></ul><p>In these scenarios, the flexibility and scalability of BASE databases offer significant advantages.</p><h2><strong>Can a Database be Both ACID and BASE?</strong></h2><p>As per the CAP theorem coined by Eric Brewer around 2000, it's challenging for a database system to simultaneously provide <em><strong>consistency, availability and partition tolerance</strong></em> properties. Generally, databases lean towards either ACID or BASE principles, but cannot be both.</p><ul><li><p><strong>ACID Databases (like SQL databases):</strong> Prioritize consistency and reliability but may not offer the same level of availability or scalability as BASE systems, especially in distributed environments.</p></li><li><p><strong>BASE Databases (like many NoSQL databases):</strong> Focus on availability and partition tolerance but do not guarantee immediate consistency across all nodes.</p></li></ul><h2>Microsoft Azure Databases</h2><p>Azure offers a wide range of database services catering to different needs, making the distinction between those that follow the ACID (Atomicity, Consistency, Isolation, Durability) model, typically associated with traditional relational databases, and those that adhere to the BASE (Basically Available, Soft state, Eventual consistency) model, common in NoSQL databases.</p><p>Understanding these options is key for selecting the right database service for your specific application requirements.</p><p>Here&#8217;s a brief overview of the most popular database options available on Azure:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Eg6z!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa95fc5cd-7daa-454a-9b2d-2543da84b2db_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Eg6z!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa95fc5cd-7daa-454a-9b2d-2543da84b2db_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!Eg6z!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa95fc5cd-7daa-454a-9b2d-2543da84b2db_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!Eg6z!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa95fc5cd-7daa-454a-9b2d-2543da84b2db_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!Eg6z!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa95fc5cd-7daa-454a-9b2d-2543da84b2db_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Eg6z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa95fc5cd-7daa-454a-9b2d-2543da84b2db_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a95fc5cd-7daa-454a-9b2d-2543da84b2db_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:577193,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Eg6z!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa95fc5cd-7daa-454a-9b2d-2543da84b2db_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!Eg6z!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa95fc5cd-7daa-454a-9b2d-2543da84b2db_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!Eg6z!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa95fc5cd-7daa-454a-9b2d-2543da84b2db_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!Eg6z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa95fc5cd-7daa-454a-9b2d-2543da84b2db_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><strong>ACID Compliant Databases</strong></h3><p>These databases prioritize transactional integrity and data consistency, following the principles of ACID:</p><ol><li><p><strong>Azure SQL Database:</strong></p><ul><li><p><strong>Type</strong>: Fully managed relational database service.</p></li><li><p><strong>Based On</strong>: Microsoft SQL Server engine.</p></li><li><p><strong>Key Features</strong>: Offers advanced SQL capabilities, built-in intelligence for performance tuning, and global scalability.</p></li><li><p><strong>Use Cases</strong>: Ideal for applications requiring complex transactions, rich data models, and strong SQL support.</p></li></ul></li><li><p><strong>Azure Database for MySQL:</strong></p><ul><li><p><strong>Type</strong>: Fully managed database service based on the open-source MySQL Server.</p></li><li><p><strong>Key Features</strong>: Built-in high availability, automatic backups, and scaling capabilities.</p></li><li><p><strong>Use Cases</strong>: Best for applications that use MySQL as their database, such as web apps, content management systems, and e-commerce platforms.</p></li></ul></li><li><p><strong>Azure Database for PostgreSQL:</strong></p><ul><li><p><strong>Type</strong>: Managed service for PostgreSQL.</p></li><li><p><strong>Key Features</strong>: Offers built-in high availability, automatic backups, and scaling. Also provides advanced features like Hyperscale (Citus) for horizontal scaling.</p></li><li><p><strong>Use Cases</strong>: Ideal for applications requiring advanced features of PostgreSQL, including geospatial capabilities, complex queries, and rich data types.</p></li></ul></li><li><p><strong>Azure Database for MariaDB:</strong></p><ul><li><p><strong>Type</strong>: Managed service for MariaDB.</p></li><li><p><strong>Key Features</strong>: Automated backups, built-in high availability, and easy scaling.</p></li><li><p><strong>Use Cases</strong>: Suitable for businesses using MariaDB for their applications, especially when there is a need for open-source compatibility.</p></li></ul></li></ol><h3><strong>BASE Compliant Databases</strong></h3><p>These databases are designed for high availability and scalability, typically following the BASE model:</p><ol><li><p><strong>Azure Cosmos DB:</strong></p><ul><li><p><strong>Type</strong>: Globally distributed, multi-model NoSQL database service.</p></li><li><p><strong>Key Features</strong>: Supports document, key-value, graph, and column-family data models. Offers turnkey global distribution, multi-region replication, and strong consistency models.</p></li><li><p><strong>Use Cases</strong>: Suitable for large-scale applications needing high availability, low latency, and support for various data models and types.</p></li></ul></li><li><p><strong>Azure Table Storage:</strong></p><ul><li><p><strong>Type</strong>: NoSQL service that stores large amounts of structured, non-relational data.</p></li><li><p><strong>Key Features</strong>: Offers a key/attribute store with a schema-less design. Cost-effective for storing massive amounts of non-relational data.</p></li><li><p><strong>Use Cases</strong>: Ideal for applications requiring flexible data schema with quick lookups and large-scale storage.</p></li></ul></li><li><p><strong>Azure Cache for Redis:</strong></p><ul><li><p><strong>Type</strong>: Fully managed in-memory data store based on Redis.</p></li><li><p><strong>Key Features</strong>: Provides high throughput and low latency data access. Ideal for caching frequently accessed data.</p></li><li><p><strong>Use Cases</strong>: Primarily used for high-performance caching, Redis can support different models depending on its configuration. While it's typically used in a manner aligning with BASE for caching scenarios, it can be configured for data persistence and some degree of transactional support.</p></li></ul></li></ol><h2><strong>Conclusion</strong></h2><p>The choice between ACID and BASE depends on the specific requirements and nature of the application.</p><ul><li><p>ACID is the go-to for applications requiring strong consistency and reliability.</p></li><li><p>BASE is ideal for scenarios where availability, flexibility, and scalability are paramount.</p></li></ul><p>Understanding the strengths and limitations of each model is crucial when designing systems that effectively meets the client&#8217;s needs and constraints.</p><p></p><div><hr></div><p>P.S. If you enjoyed this post, share it with your friends and colleagues.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/p/the-ph-of-a-database?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thesunshinelayer.com/p/the-ph-of-a-database?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Sunshine Layer! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Messaging basics with Azure services]]></title><description><![CDATA[Did you know that the choice between using queues or topics, commands or events in your messaging system can pivot the entire direction of your application's communication flow?]]></description><link>https://www.thesunshinelayer.com/p/messaging-basics-with-azure-services</link><guid isPermaLink="false">https://www.thesunshinelayer.com/p/messaging-basics-with-azure-services</guid><dc:creator><![CDATA[Elena Sunshine]]></dc:creator><pubDate>Sat, 20 Jan 2024 15:15:15 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/0c939296-ed69-4418-a316-621ce659b4de_4200x3000.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As a software engineer, understanding the basics of messaging is essential.</p><p>Let&#8217;s face it, as systems evolve, they become chattier and chattier and it is critical to ensure their reliability while also mitigate costs.</p><p>To achieve this, it's crucial to understand the <strong>differences between queues and topics, events and commands</strong>, and to <strong>know what the right messaging service</strong> for your system is.</p><p>In this article, I'll cover all these aspects, along with an in-depth look at all the <strong>Azure messaging services</strong>.</p><p>Let's explore them one by one.</p><h2><strong>Queue or Topic?</strong></h2><p>Both are used in messaging systems for communication between different parts of a system. But they have distinct characteristics:</p><h3><strong>&#8594; Queues</strong></h3><p>They <em><strong>follow a point-to-point model</strong></em>. Messages sent to a queue are processed by only one consumer.</p><p><em><strong>Each message in a queue is processed once and only once</strong></em>. It's a method of ensuring that a particular task is executed only once.</p><p>Some <em>use case examples</em> would involve processing a specific job such as generating a report or sending an email.</p><h3><strong>&#8594; Topics</strong></h3><p>Are <em><strong>based on a pub-sub model</strong></em>, where messages are published to a topic and <em><strong>multiple subscribers can listen and receive these messages</strong></em>.</p><p><em><strong>A single message sent to a topic can be received by multiple subscribers.</strong></em></p><p>This is useful for broadcasting messages.</p><p>Some <em>use case examples</em> would involve updating multiple microservices about a change in the state of a user&#8217;s order.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IAQ7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad19861c-18f2-44c3-bf5e-0d6a234e6a18_1427x1427.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IAQ7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad19861c-18f2-44c3-bf5e-0d6a234e6a18_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!IAQ7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad19861c-18f2-44c3-bf5e-0d6a234e6a18_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!IAQ7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad19861c-18f2-44c3-bf5e-0d6a234e6a18_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!IAQ7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad19861c-18f2-44c3-bf5e-0d6a234e6a18_1427x1427.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IAQ7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad19861c-18f2-44c3-bf5e-0d6a234e6a18_1427x1427.gif" width="1427" height="1427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ad19861c-18f2-44c3-bf5e-0d6a234e6a18_1427x1427.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1427,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:714093,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IAQ7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad19861c-18f2-44c3-bf5e-0d6a234e6a18_1427x1427.gif 424w, https://substackcdn.com/image/fetch/$s_!IAQ7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad19861c-18f2-44c3-bf5e-0d6a234e6a18_1427x1427.gif 848w, https://substackcdn.com/image/fetch/$s_!IAQ7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad19861c-18f2-44c3-bf5e-0d6a234e6a18_1427x1427.gif 1272w, https://substackcdn.com/image/fetch/$s_!IAQ7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad19861c-18f2-44c3-bf5e-0d6a234e6a18_1427x1427.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><strong>Comparison</strong></h3><p>The choice between using queues or topics depends on the specific requirements of your system.</p><p><em><strong>Queues</strong></em> are better suited for situations where a specific action needs to be taken, with <em><strong>each message processed only once</strong></em>.</p><p><em><strong>Topics</strong></em> are ideal for situations where <em><strong>a message or notification needs to be broadcasted to multiple parts of the system</strong></em> without expecting a direct response.</p><p></p><h2><strong>Command or Event?</strong></h2><p>While they both are types of messages in a system, they serve different purposes and imply different behaviors.</p><h3><strong>&#8594; Commands</strong></h3><p>A command is <em><strong>a directive</strong></em> to perform a specific action. It's an instruction to the system to change its state, usually <em><strong>named in the imperative mood</strong></em> (e.g., <code>CreateOrder, ShipItem</code>).</p><p>Commands are <strong>active</strong>. When a command is sent, it's expected that the <em><strong>receiving component will act upon it</strong></em>. It is a form of request from one part of the system to another.</p><p><strong>Commands are targeted</strong>, usually sent to a specific component or service responsible for handling them.</p><h4><em><strong>Use Cases</strong></em></h4><p>Commands are used when the intention is to cause a change or perform an action. For instance, a <code>ProcessPayment</code> command would instruct the system to execute the steps associated with processing a payment.</p><h3><strong>&#8594; Events</strong></h3><p>An event is <em><strong>a notification</strong></em> that something has happened.</p><p>It's a statement of fact and is typically <em><strong>named in the past tense</strong></em> (e.g. <code>OrderCreated, ItemShipped</code>).</p><p>Events are <em><strong>passive</strong></em>. When an event is sent out, it does not expect a direct action to be taken in response.</p><p>Can be <em><strong>broadcast to multiple listeners or handlers</strong></em> who may choose to act upon them.</p><p>They <em><strong>help in decoupling the system</strong></em>. The <em><strong>publisher of the event does not need to know who is consuming</strong></em> or listening to the event.</p><h4><em><strong>Use Cases</strong></em></h4><p>Events are used for notifying the system about changes in state or other occurrences. For example, an <code>OrderCreated</code> event might trigger various actions like updating inventory, notifying the user, or initiating a billing process.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!10Nk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddfe71f-3b31-4804-8b63-3bcf1d125955_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!10Nk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddfe71f-3b31-4804-8b63-3bcf1d125955_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!10Nk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddfe71f-3b31-4804-8b63-3bcf1d125955_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!10Nk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddfe71f-3b31-4804-8b63-3bcf1d125955_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!10Nk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddfe71f-3b31-4804-8b63-3bcf1d125955_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!10Nk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddfe71f-3b31-4804-8b63-3bcf1d125955_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2ddfe71f-3b31-4804-8b63-3bcf1d125955_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:371510,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!10Nk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddfe71f-3b31-4804-8b63-3bcf1d125955_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!10Nk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddfe71f-3b31-4804-8b63-3bcf1d125955_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!10Nk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddfe71f-3b31-4804-8b63-3bcf1d125955_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!10Nk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddfe71f-3b31-4804-8b63-3bcf1d125955_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><strong>&#8594; Key Differences</strong></h3><h4>1. Intent</h4><p><em><strong>Commands request</strong></em> that something should happen.</p><p><em><strong>Events inform</strong></em> that something has happened.</p><h4><strong>2. Direction</strong></h4><p><em><strong>Commands are directed</strong></em> at a specific target with the expectation of a response or action.</p><p><em><strong>Events are a broadcaster</strong></em>, notifying the broader system and don't care much about the response.</p><h4><strong>3. Payload</strong></h4><p><em><strong>Commands have a rich payload</strong></em> usually, containing all the necessary data for the specific component to be able to fulfil the request.</p><p><em><strong>Events are slimmer</strong></em>, not knowing what data the interested parts of the system might need to perform their respective actions.</p><h4><strong>4. Coupling</strong></h4><p><em><strong>Commands can imply tighter coupling</strong></em> between the requester and the performer of the action.</p><p><em><strong>Events tend to support looser coupling</strong></em> between components (publishers don't need to know about subscribers)</p><h3><strong>How to decide what to choose?</strong></h3><h4><em><strong>1. Evaluate the nature of the interaction.</strong></em></h4><p>If the interaction is about notifying other parts of the system about changes or occurrences without expecting a direct action, use events. If it's about explicitly requesting an action or change, use commands.</p><h4><em><strong>2. Consider the system design.</strong></em></h4><p>Assess how tightly coupled your components are and how much you want them to know about each other. Events can help in creating a more decoupled architecture.</p><h4><em><strong>3. Ponder complexity and scalability.</strong></em></h4><p>Commands can make workflows and user actions more explicit and traceable. Events can be more scalable and can simplify complex interactions by decoupling components.</p><p><strong>Comparison</strong> <em><strong>Events are about notifying the system</strong></em> of occurrences and allowing independent components to react as needed, promoting loose coupling. <em><strong>Commands are about explicitly requesting actions or changes</strong></em>, often implying a more tightly coupled interaction.</p><p></p><h2><strong>Azure Messaging Services</strong></h2><p>Azure offers a variety of messaging services tailored to different needs, from simple queues to complex event routing. Understanding the features, use cases, and differences between these options is crucial for designing an effective architecture. Here's a comparison of Azure's primary messaging systems:</p><h3><strong>1. Azure Queue Storage</strong></h3><ul><li><p><strong>Overview</strong>: A simple, cost-effective service for storing large numbers of messages that can be accessed from anywhere via authenticated calls using HTTP or HTTPS.</p></li><li><p><strong>Use Cases</strong>: Ideal for simple tasks such as background tasks, job scheduling, and batch processing.</p></li><li><p><strong>Pros</strong>: Easy to use, highly scalable, and economical.</p></li><li><p><strong>Cons</strong>: Limited to simple scenarios, lacks advanced features like topic-based subscriptions or filtering.</p></li></ul><h3><strong>2. Azure Service Bus</strong></h3><ul><li><p><strong>Overview</strong>: A more advanced enterprise-level messaging system that supports queues, publish-subscribe (topics), and more complex integration patterns.</p></li><li><p><strong>Use Cases</strong>: Suitable for high-value enterprise messaging where topics, sessions, transactions, and ordering are required.</p></li><li><p><strong>Pros</strong>: Offers advanced features like FIFO (First-In, First-Out) messaging, duplicate detection, and deferred messages.</p></li><li><p><strong>Cons</strong>: More expensive than Azure Queue Storage and can be overkill for simple needs.</p></li></ul><h3><strong>3. Azure Event Hubs</strong></h3><ul><li><p><strong>Overview</strong>: A highly scalable data streaming platform and event ingestion service, capable of receiving and processing millions of events per second.</p></li><li><p><strong>Use Cases</strong>: Ideal for big data scenarios, telemetry, data analytics pipelines, and application logging.</p></li><li><p><strong>Pros</strong>: Exceptional performance and scale, capable of handling massive amounts of event data.</p></li><li><p><strong>Cons</strong>: Focuses more on event streaming than message operations like dead-lettering or message deferral.</p></li></ul><h3><strong>4. Azure Event Grid</strong></h3><ul><li><p><strong>Overview</strong>: A fully-managed event routing service that uses a publish-subscribe model for uniform event consumption.</p></li><li><p><strong>Use Cases</strong>: Perfect for reactive programming, integrating with various Azure services, and building event-driven architectures.</p></li><li><p><strong>Pros</strong>: Provides filtering, multicasting, and event fan-out capabilities. It's deeply integrated with Azure services and supports custom webhooks.</p></li><li><p><strong>Cons</strong>: Primarily focused on event signaling rather than data transfer and doesn't support long polling or other typical message queue functions.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cDi3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9497ebf7-9de3-4fc6-92a4-6946c7a6cd63_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cDi3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9497ebf7-9de3-4fc6-92a4-6946c7a6cd63_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!cDi3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9497ebf7-9de3-4fc6-92a4-6946c7a6cd63_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!cDi3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9497ebf7-9de3-4fc6-92a4-6946c7a6cd63_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!cDi3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9497ebf7-9de3-4fc6-92a4-6946c7a6cd63_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cDi3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9497ebf7-9de3-4fc6-92a4-6946c7a6cd63_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9497ebf7-9de3-4fc6-92a4-6946c7a6cd63_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:575453,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cDi3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9497ebf7-9de3-4fc6-92a4-6946c7a6cd63_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!cDi3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9497ebf7-9de3-4fc6-92a4-6946c7a6cd63_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!cDi3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9497ebf7-9de3-4fc6-92a4-6946c7a6cd63_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!cDi3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9497ebf7-9de3-4fc6-92a4-6946c7a6cd63_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><strong>Comparison and Considerations</strong></h3><h4><strong>1. Scalability</strong></h4><p>While all services offer high scalability, Event Hubs is the go-to for massive-scale event ingestion, and Service Bus is better for enterprise-level messaging.</p><h4><strong>2. Complexity and Features</strong></h4><p>Service Bus offers complex features and patterns, suitable for intricate messaging needs, whereas Queue Storage is for simple scenarios. Event Grid excels in routing and handling events from various sources.</p><h4><strong>3. Pricing</strong></h4><p>Costs can vary significantly. Queue Storage is generally the most economical, while Service Bus and Event Hubs might incur higher costs due to their advanced capabilities.</p><h4><strong>4. Integration</strong></h4><p>Consider how well each service integrates with your existing architecture. Event Grid and Event Hubs offer seamless integration with many Azure services.</p><p>Selecting the right messaging option in Azure depends on the specific requirements of your application, such as the nature of the data, required throughput, desired features, and cost considerations.</p><ul><li><p>For <em><strong>simple queue-based messaging, Azure Queue Storage</strong></em> is straightforward and cost-effective.</p></li><li><p>For more <em><strong>complex enterprise messaging, Azure Service Bus</strong></em> offers robust features.</p></li><li><p>For <em><strong>massive-scale event processing, Azure Event Hubs</strong></em> is unparalleled.</p></li><li><p>For <em><strong>event routing and reactive programming, Azure Event Grid</strong></em> provides excellent capabilities.</p></li></ul><p>Understanding the strengths and use cases of each service allows you to make an informed decision that best suits your application's needs.</p><div><hr></div><p>P.S. If you enjoyed this post, share it with your friends and colleagues.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/p/messaging-basics-with-azure-services?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thesunshinelayer.com/p/messaging-basics-with-azure-services?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Sunshine Layer! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[CQS and CQRS: Twins or Distant Cousins?]]></title><description><![CDATA[When it comes to software engineering, we have a knack for acronyms. And two that often get mixed up are CQS and CQRS. Although might seem similar, they serve different purposes.]]></description><link>https://www.thesunshinelayer.com/p/cqs-and-cqrs-twins-or-distant-cousins</link><guid isPermaLink="false">https://www.thesunshinelayer.com/p/cqs-and-cqrs-twins-or-distant-cousins</guid><dc:creator><![CDATA[Elena Sunshine]]></dc:creator><pubDate>Sat, 13 Jan 2024 13:01:01 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/7500f7d1-999a-4a1a-8970-a01152b02466_420x300.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When it comes to software engineering, we have a knack for acronyms. And two that often get mixed up are <em><strong>CQS and CQRS</strong></em>.</p><p>At first glance, you might think they&#8217;re one and the same, akin to twins, but look a little closer and you'll find they're more like distant cousins.</p><p>Here's why.</p><p><strong>CQS (Command Query Separation): General behavioral principle</strong> Coined by Bertrand Meyer in his book '<a href="https://en.wikipedia.org/wiki/Object-Oriented_Software_Construction">Object-oriented Software Construction</a>' (1988, Prentice Hall), <strong>CQS is a principle</strong> asserting that an object's <em><strong>methods should either be Commands or Queries, but never both</strong></em>.</p><ul><li><p>Commands <strong>perform an action.</strong></p></li><li><p>Queries solely <strong>return data.</strong></p></li></ul><p>If you consider the codebase to be a bustling city, CQS applies the <em><strong>traffic laws</strong></em> to ensure everything flows smoothly.</p><p>It keeps the streets (methods) clear of accidents (unexpected side effects) by preventing the same method from making changes AND broadcasting those changes.</p><p>Let's look closer at this traffic management system. Let's say a method is responsible for both registering a vehicle's speed and determining if it's exceeding the speed limit.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iYpM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbdf028a-9c2e-4d15-9a16-c3de9c758362_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iYpM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbdf028a-9c2e-4d15-9a16-c3de9c758362_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!iYpM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbdf028a-9c2e-4d15-9a16-c3de9c758362_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!iYpM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbdf028a-9c2e-4d15-9a16-c3de9c758362_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!iYpM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbdf028a-9c2e-4d15-9a16-c3de9c758362_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iYpM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbdf028a-9c2e-4d15-9a16-c3de9c758362_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cbdf028a-9c2e-4d15-9a16-c3de9c758362_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:506476,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!iYpM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbdf028a-9c2e-4d15-9a16-c3de9c758362_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!iYpM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbdf028a-9c2e-4d15-9a16-c3de9c758362_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!iYpM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbdf028a-9c2e-4d15-9a16-c3de9c758362_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!iYpM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbdf028a-9c2e-4d15-9a16-c3de9c758362_2380x2380.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This violates the Command Query Separation principle as it combines a side effect (recording the speed) with information retrieval (checking for a speed limit breach).</p><p></p><p>Let's fix that simply by <strong>separating the state-changing behavior from the state-retrieving one</strong>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VK2f!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94ac7f86-4b45-4b5c-800a-38427c33e043_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VK2f!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94ac7f86-4b45-4b5c-800a-38427c33e043_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!VK2f!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94ac7f86-4b45-4b5c-800a-38427c33e043_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!VK2f!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94ac7f86-4b45-4b5c-800a-38427c33e043_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!VK2f!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94ac7f86-4b45-4b5c-800a-38427c33e043_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VK2f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94ac7f86-4b45-4b5c-800a-38427c33e043_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/94ac7f86-4b45-4b5c-800a-38427c33e043_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:476551,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!VK2f!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94ac7f86-4b45-4b5c-800a-38427c33e043_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!VK2f!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94ac7f86-4b45-4b5c-800a-38427c33e043_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!VK2f!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94ac7f86-4b45-4b5c-800a-38427c33e043_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!VK2f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94ac7f86-4b45-4b5c-800a-38427c33e043_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This separation clarifies the responsibilities of each method, making the code easier to read, understand, and maintain. It also prevents unexpected side effects, which are common in methods that combine querying and state modification. By creating this distinction you&#8217;ll be much more confident to mix and match queries tailored to your needs. With commands you&#8217;ll still need to be thoughtful.</p><p>Now, of course that doesn&#8217;t mean we need to be complete purists when it comes CQS, especially when it comes to returning a value from a command.</p><p>Exceptions occur, such as when you&#8217;re creating a new entity and you return an id. But while commands returning a value is not the end of the world, it&#8217;s crucial you <strong>don&#8217;t alter the state in a query</strong>.</p><p>All in all, when applied at the method or class level, <em><strong>CQS is all about clarity in design and making your code easier to reason about</strong></em>.</p><p></p><p><strong>CQRS (Command Query Responsibility Segregation): The Architectural Evolution</strong></p><p>CQRS takes the <strong>essence of CQS</strong> and expands it <strong>into</strong> the realm of <strong>system design</strong>.</p><p>Here, the game changes.</p><p>We're <strong>no longer talking about methods. We&#8217;re talking abut </strong><em><strong>segregating the entire system into two parts</strong></em><strong>:</strong></p><ul><li><p><strong>one for commands (writes)</strong></p></li><li><p><strong>one for queries (reads)</strong>.</p></li></ul><p>Think of your system using <strong>two separate databases</strong>:</p><ul><li><p><strong>one for reading the data</strong>.</p></li><li><p><strong>one for writing data in</strong>.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!o2fw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4e6b155-4171-447f-b2c8-3410ca7930e6_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!o2fw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4e6b155-4171-447f-b2c8-3410ca7930e6_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!o2fw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4e6b155-4171-447f-b2c8-3410ca7930e6_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!o2fw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4e6b155-4171-447f-b2c8-3410ca7930e6_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!o2fw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4e6b155-4171-447f-b2c8-3410ca7930e6_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!o2fw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4e6b155-4171-447f-b2c8-3410ca7930e6_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c4e6b155-4171-447f-b2c8-3410ca7930e6_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:284426,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!o2fw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4e6b155-4171-447f-b2c8-3410ca7930e6_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!o2fw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4e6b155-4171-447f-b2c8-3410ca7930e6_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!o2fw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4e6b155-4171-447f-b2c8-3410ca7930e6_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!o2fw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4e6b155-4171-447f-b2c8-3410ca7930e6_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Why the split?</p><p>To allow independent scalability and optimization.</p><p>With CQRS, you can scale your read and write workloads independently. You're free to optimize and modify the read side without touching the writes, and vice versa.</p><p>It's having two specialists handling what they do best.</p><p>Now, of course it&#8217;s not compulsory to have two databases in order to apply CQRS. You can begin implementing CQRS starting with a logical separation between your read and update models in your system and grow from there, balancing scalability and simplicity.</p><p>Because with great power comes...you guessed it: complexity.</p><p>Implementing CQRS isn't a walk in the park.</p><p>You're dealing with separate models, tackling consistency concerns, and often venturing into eventual consistency territory.</p><p>It's a trade-off, a balancing act between scalability and simplicity.</p><p><strong>Event Sourcing: Time Travel Made Possible</strong></p><ul><li><p><em><strong>CQS:</strong></em></p><ul><li><p>Mostly on the sidelines for this play.</p></li><li><p>It doesn&#8217;t inherently interact with or leverage event sourcing.</p></li></ul></li><li><p><em><strong>CQRS:</strong></em></p><ul><li><p>A frequent collaborator with event sourcing.</p></li><li><p>It elegantly stores changes as a breadcrumb trail of events, allowing systems to rewind, replay, and predict.</p></li></ul></li></ul><p><strong>Consistency: A Balancing Act</strong></p><ul><li><p><em><strong>CQS:</strong></em></p><ul><li><p>Operates in a world where consistency is a given, not a luxury.</p></li><li><p>It&#8217;s all local, straightforward interactions here.</p></li></ul></li><li><p><em><strong>CQRS:</strong></em></p><ul><li><p>Walks a tightrope with consistency, especially in distributed systems.</p></li><li><p>Immediate consistency isn't always a guarantee, making way for its more relaxed cousin, eventual consistency.</p></li></ul></li></ul><p><strong>Integration with Other Patterns:</strong></p><ul><li><p><em><strong>CQS</strong></em><strong>:</strong></p><ul><li><p>It is a principle that&#8217;s more internal and localized.</p></li><li><p>It doesn't necessarily dictate or heavily influence the broader architectural decisions and is often orthogonal to other patterns.</p></li><li><p>It&#8217;s about making the individual components of a system (the methods) more understandable and manageable, reducing complexity where functionality and data retrieval are concerned.</p></li></ul></li><li><p><em><strong>CQRS</strong></em><strong>:</strong></p><ul><li><p>It&#8217;s a top-tier player in system design, often used in concert with other high-level patterns.</p></li><li><p>It pairs exceptionally well with event sourcing, where the system's state changes are logged as a series of immutable events.</p></li><li><p>This relationship allows for advanced capabilities, like <em><strong>system snapshots</strong></em> or an <em><strong>audit log</strong></em> with "undo" functionality.</p></li></ul></li></ul><p><strong>Complexity and Suitability:</strong></p><ul><li><p><em><strong>CQS</strong></em><strong>:</strong></p><ul><li><p>Given its method-level governance, adopting <strong>CQS</strong> doesn't require a significant overhaul of the system architecture.</p></li><li><p>Suitable for systems of various sizes.</p></li><li><p>It demands a cultural shift in how developers approach writing methods/functions, <strong>aiming for pure, side-effect-free functions</strong>.</p></li></ul></li><li><p><em><strong>CQRS</strong></em><strong>:</strong></p><ul><li><p>Implementing CQRS is no small feat.</p></li><li><p>It involves a fundamental restructuring of how the system handles data.</p></li><li><p>It's ideal for large-scale, enterprise-level applications where <strong>scalability, high performance, and reliability</strong> are paramount.</p></li><li><p>Its trade-off is <strong>increased complexity in data consistency and transaction management</strong>, potentially leading to higher initial development and maintenance costs.</p></li></ul></li></ul><p><strong>Conclusion</strong> CQS and CQRS, though stemming from similar principles, serve two different purposes.</p><p><strong>CQS excels in method-level</strong> clarity and directness.</p><p><strong>CQRS tackles system-wide segregation, scalability,</strong> and embraces <strong>complexity</strong>.</p><p>They are not just acronyms, but approaches tailored for specific paths in software engineering.</p><div><hr></div><p>P.S. If you enjoyed this post, share it with your friends and colleagues.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Sunshine Layer! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Latency explained]]></title><description><![CDATA[If you want to build high-performance systems, it's crucial to understand latency. Read on to find out what various events' latencies scale to in a more relatable version and how to improve latency.]]></description><link>https://www.thesunshinelayer.com/p/latency-explained</link><guid isPermaLink="false">https://www.thesunshinelayer.com/p/latency-explained</guid><dc:creator><![CDATA[Elena Sunshine]]></dc:creator><pubDate>Fri, 05 Jan 2024 00:32:22 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!iyRp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68013b-0c12-4728-a3b1-58b7bc258200_2380x2380.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thesunshinelayer.com/subscribe?"><span>Subscribe now</span></a></p><p>Latency is so important to master that Gmail&#8217;s creator, Paul Buchheit, even coined a rule in regards to it: the <em>100ms rule.</em></p><p>But more on that later. Let&#8217;s first start with the basics.</p><h2><strong>What is latency?</strong></h2><p>It refers to how fast a signal or data packet travels from one point to another in a network or system. It's essentially a delay measured in milliseconds (ms) or even microseconds (&#181;s). Latency significantly impacts system performance and user experience.</p><h4>When we talk latency, we can split it into <strong>different types</strong>:</h4><ul><li><p><strong>Network Latency</strong>: The time taken for a data packet to travel across a network from sender to receiver.</p></li><li><p><strong>Disk Latency</strong>: The time it takes for a disk to complete a read or write operation.</p></li><li><p><strong>Processing Latency</strong>: The time it takes for a system to process a given input.</p></li></ul><p>Now circling back to the 100ms rule.</p><p>It states that every interaction should be quicker than 100ms.</p><p>Why?</p><p>Because 100ms is the threshold &#8220;where interactions feel instantaneous.&#8221;</p><h2><strong>But how fast is 100ms really?</strong></h2><p>The chart illustrates various computer and network events with their latencies, presented in <em><strong>actual time</strong></em> (nanoseconds to seconds) <em><strong>and a</strong> <strong>scaled</strong></em>, more <em><strong>relatable version</strong></em> for our common understanding.</p><p>While the actual latencies might seem incredibly short, the scaled version provides a perspective on their relative impact.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iyRp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68013b-0c12-4728-a3b1-58b7bc258200_2380x2380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iyRp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68013b-0c12-4728-a3b1-58b7bc258200_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!iyRp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68013b-0c12-4728-a3b1-58b7bc258200_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!iyRp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68013b-0c12-4728-a3b1-58b7bc258200_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!iyRp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68013b-0c12-4728-a3b1-58b7bc258200_2380x2380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iyRp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68013b-0c12-4728-a3b1-58b7bc258200_2380x2380.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ce68013b-0c12-4728-a3b1-58b7bc258200_2380x2380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:427529,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!iyRp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68013b-0c12-4728-a3b1-58b7bc258200_2380x2380.png 424w, https://substackcdn.com/image/fetch/$s_!iyRp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68013b-0c12-4728-a3b1-58b7bc258200_2380x2380.png 848w, https://substackcdn.com/image/fetch/$s_!iyRp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68013b-0c12-4728-a3b1-58b7bc258200_2380x2380.png 1272w, https://substackcdn.com/image/fetch/$s_!iyRp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68013b-0c12-4728-a3b1-58b7bc258200_2380x2380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h4><strong>Notes:</strong></h4><ul><li><p><strong>Actual Latency</strong>: Given in nanoseconds (ns), microseconds (&#181;s), milliseconds (ms), or seconds (s). Represents the real-time it takes for the event.</p></li><li><p><strong>Scaled Latency</strong>: A metaphorical translation to a human-understandable timescale, showing how we might perceive these latencies if they were stretched out.</p></li></ul><h3><strong>Key Network Events and Latencies</strong></h3><ul><li><p><strong>CPU Cycle</strong>: The base of all computations. Lower cycle times mean faster processing but understanding the latency from memory access is crucial for optimizing performance.</p></li><li><p><strong>Cache Access:</strong> Different levels of cache have varying access speeds. Optimizing which data is stored in each can vastly improve performance.</p></li><li><p><strong>Memory Access:</strong> Accessing RAM is significantly slower than accessing CPU cache. Knowing this helps in designing systems that minimize memory access bottlenecks.</p></li><li><p><strong>Disk I/O:</strong> Both SSDs and HDDs have latencies orders of magnitude higher than memory access. Systems designed to reduce disk access can greatly benefit.</p></li><li><p><strong>Network Requests:</strong> The latency involved in sending data over a network can be unpredictable and varies greatly. Efficient network protocols and data caching strategies are vital.</p></li><li><p><strong>Reboots and Timeouts:</strong> The longest latencies come from system reboots and timeouts, scaling to hundreds and even thousands of years, underscoring the relative slowness of these operations in the digital realm.</p></li></ul><h2><strong>Why Latency Matters?</strong></h2><p>It's crucial across all tech sectors. For example:</p><p>Here are some examples:</p><ul><li><p><strong>Cloud Computing and Data Centers</strong></p><p>Amazon found that every 100ms delay in web page loading time can lead to a 1% loss in sales. This means that for a company like Amazon, with sales of $514 billion in 2022, a mere 100ms delay could potentially cost around $5.14 billion in sales annually.</p></li><li><p><strong>Online Gaming</strong></p><p>Riot Games reported that when they improved the latency for "League of Legends" players in North America by moving servers, there was a notable increase in player engagement. Players in affected regions played up to 7% more games when they experienced a 10-30ms improvement in latency.</p></li><li><p><strong>Streaming Services</strong></p><p>Netflix's research revealed that a delay of 2 seconds in video start-up time increased the chance of abandonment by 6%. Moreover, for every 0.5 seconds of additional buffering, there are 1% fewer starts of any videos on their platform.</p></li><li><p><strong>Financial Trading</strong></p><p>In the world of high-frequency trading, a 1 millisecond advantage in trading applications can be worth $100 million a year to a major brokerage firm, as reported by TABB Group.</p></li><li><p><strong>Healthcare and Telemedicine</strong></p><p>According to a study by the American Telemedicine Association, the use of telestroke services (rapid response video consultations for stroke victims) in rural areas, where quick response is critical, resulted in as much as a 25% decrease in patient disability. This is highly dependent on low-latency connections for real-time video consultations.</p></li><li><p><strong>Automotive and Transport</strong></p><p>For autonomous vehicles, a study suggested that reducing latency from 100ms to 10ms in vehicle communication systems can decrease collision rates by 20-30%. This could potentially save thousands of lives considering there were an estimated 38,800 traffic fatalities in the US alone in 2019.</p></li><li><p><strong>Virtual and Augmented Reality</strong></p><p>In a study conducted by Nvidia, they found that reducing latency from 50ms to 20ms in VR systems reduced user discomfort significantly, with reports of nausea dropping by over 50%. This can lead to longer, more engaging VR experiences and higher user retention rates.</p></li></ul><h2>How can you m<strong>itigate latency</strong></h2><ul><li><p><strong>Profiling and Monitoring</strong>: Regularly profile and monitor applications to understand where latencies are occurring.</p></li><li><p><strong>Caching Strategies</strong>: Implement effective caching to reduce the need to access slower storage.</p></li><li><p><strong>Asynchronous Programming</strong>: Use asynchronous operations to prevent application blocking during long operations.</p></li><li><p><strong>Optimize Data Transfer</strong>: Minimize data sent over the network and use efficient serialization methods.</p></li><li><p><strong>Choose the Right Tools</strong>: Use databases, libraries, and frameworks known for performance and suited for your specific needs.</p></li><li><p><strong>Optimize Code</strong>: Ensure that your application code is efficient and not causing unnecessary delays.</p></li><li><p><strong>Upgrade Hardware</strong>: Use faster processors, more RAM, or SSDs instead of HDDs to reduce processing and disk latency. Yes, that translates to faster resources in the cloud.</p></li><li><p><strong>Content Delivery Networks (CDN)</strong>: For web applications, use CDNs to cache content closer to users, reducing network latency.</p></li><li><p><strong>Load Balancing</strong>: Distribute traffic evenly across servers to avoid overloading any single resource.</p></li><li><p><strong>Network Optimization</strong>: Use network optimization techniques like compression or faster protocols to reduce data transmission times.</p></li></ul><h2><strong>Conclusion</strong></h2><p>While inherent in all systems, understanding and reducing latency can greatly enhance performance and user satisfaction. By recognizing the sources of latency and implementing strategies to mitigate it, you can ensure that your system remains efficient, responsive, and scalable.</p><p>Whether you're a network administrator, a software developer, or a system architect, managing latency effectively is a key part of optimizing the performance and reliability of your operations.</p><p></p><div><hr></div><p>P.S. If you enjoyed this post, share it with your friends and colleagues.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thesunshinelayer.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Sunshine Layer! Subscribe for free to receive weekly insights on software development and system design.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item></channel></rss>