<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: 🧑‍💻 Kamil Bączek</title>
    <description>The latest articles on Forem by 🧑‍💻 Kamil Bączek (@kamilbaczek).</description>
    <link>https://forem.com/kamilbaczek</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F963850%2Fb71c3b52-6162-448e-a65f-32abed1b3006.jpg</url>
      <title>Forem: 🧑‍💻 Kamil Bączek</title>
      <link>https://forem.com/kamilbaczek</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kamilbaczek"/>
    <language>en</language>
    <item>
      <title>Evolutionary Architecture by Example 🚀</title>
      <dc:creator>🧑‍💻 Kamil Bączek</dc:creator>
      <pubDate>Mon, 18 Sep 2023 11:58:23 +0000</pubDate>
      <link>https://forem.com/kamilbaczek/evolutionary-architecture-by-example-first-release-4bca</link>
      <guid>https://forem.com/kamilbaczek/evolutionary-architecture-by-example-first-release-4bca</guid>
      <description>&lt;p&gt;Hey there, fellow developers and architects!&lt;/p&gt;

&lt;p&gt;We're thrilled to introduce our latest project, the &lt;strong&gt;"Evolutionary Architecture by example"&lt;/strong&gt; repository. This collaborative effort, brought to you by Maciej Jedrzejewski and me, represents countless hours of dedication and hard work. Join us on a journey into the intricate world of architectural evolution within the .NET ecosystem.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/evolutionary-architecture"&gt;
        evolutionary-architecture
      &lt;/a&gt; / &lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example"&gt;
        evolutionary-architecture-by-example
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Navigate the complex landscape of .NET software architecture with our step-by-step, story-like guide. Unpack the interplay between modular monoliths, microservices, domain-driven design, and various architectural patterns. Go beyond the one-size-fits-all solutions and understand how to blend these approaches based on your unique needs.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="adoc"&gt;
&lt;h1&gt;
Evolutionary Architecture&lt;/h1&gt;
&lt;div id="user-content-toc"&gt;
&lt;div id="user-content-toctitle"&gt;Table of Contents&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#objective"&gt;Objective&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#problem"&gt;Problem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#proposed-solution"&gt;Proposed Solution&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#domain"&gt;Domain&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#overview"&gt;Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#subdomains"&gt;Subdomains&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#potential-patterns"&gt;Potential Patterns&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#chapters"&gt;Chapters&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#chapter-1-initial-architecture-focus-on-simplicity"&gt;Chapter 1: Initial Architecture: Focus On Simplicity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#chapter-2-modules-separation-focus-on-maintainability"&gt;Chapter 2: Modules Separation: Focus On Maintainability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#chapter-3-microservice-extraction-focus-on-growth"&gt;Chapter 3: Microservice Extraction: Focus On Growth&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#chapter-4-applying-tactical-domain-driven-design-focus-on-complexity"&gt;Chapter 4: Applying Tactical Domain-Driven Design: Focus On Complexity&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#repository-structure"&gt;Repository Structure&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#overview-1"&gt;Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#how-to-navigate"&gt;How To Navigate?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#libraries-and-platforms-used"&gt;Libraries and Platforms Used&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#videos"&gt;Videos 🎥&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#webinar-from-architecture-weekly"&gt;Webinar from Architecture Weekly 🇬🇧&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#presentation-at-programistok-2023-conference"&gt;Presentation at Programistok 2023 Conference 🇵🇱&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#authors"&gt;Authors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#join-our-community"&gt;💬 Join our Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example#say-thanks"&gt;⭐ Say thanks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id="user-content-preamble"&gt;
&lt;div&gt;
&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-exampleAssets/ea_banner.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ItC71q-J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/evolutionary-architecture/evolutionary-architecture-by-exampleAssets/ea_banner.png" width="350" height="350" alt="ea banner"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/327e4ef6b03b55bb821c3d6c65f88245117de3dc951c0607eef06eb0e25a19c9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65"&gt;&lt;img src="https://camo.githubusercontent.com/327e4ef6b03b55bb821c3d6c65f88245117de3dc951c0607eef06eb0e25a19c9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65" alt="realease"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/124a8c37daf9b0429d5a37f342beac74a9c6f5d03fb1db6f9598a197c4193ff1/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65"&gt;&lt;img src="https://camo.githubusercontent.com/124a8c37daf9b0429d5a37f342beac74a9c6f5d03fb1db6f9598a197c4193ff1/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65" alt="License Badge"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/ec94ef349874021f5ad3d2a357b43fb550807cc9e41131be9fc3b036134053a6/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65"&gt;&lt;img src="https://camo.githubusercontent.com/ec94ef349874021f5ad3d2a357b43fb550807cc9e41131be9fc3b036134053a6/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65" alt="Stars Badge"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/52059807df9af79a305e74fa0b8a121d007a1147ef7d2b1d870aee362361318e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636f6d6d69742d61637469766974792f6d2f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65"&gt;&lt;img src="https://camo.githubusercontent.com/52059807df9af79a305e74fa0b8a121d007a1147ef7d2b1d870aee362361318e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636f6d6d69742d61637469766974792f6d2f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65" alt="Commits Badge"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/42f121d41ac3f2c19174dc8c106bf07ed5918e20ae706599b23c4fdfc87e7b2f/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65"&gt;&lt;img src="https://camo.githubusercontent.com/42f121d41ac3f2c19174dc8c106bf07ed5918e20ae706599b23c4fdfc87e7b2f/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65" alt="Last Commit Badge"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/2d5db1a3c8fe45b0189b9ed72b3343df63085668fea372e2b4ceb1f52423ae78/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65"&gt;&lt;img src="https://camo.githubusercontent.com/2d5db1a3c8fe45b0189b9ed72b3343df63085668fea372e2b4ceb1f52423ae78/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65" alt="Issues Badge"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/518ccce1e0cac2a1449560b62d248342bb59bb0e6e380c1e00b1a334eb419c87/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732d70722f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65"&gt;&lt;img src="https://camo.githubusercontent.com/518ccce1e0cac2a1449560b62d248342bb59bb0e6e380c1e00b1a334eb419c87/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732d70722f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65" alt="Pull Requests Badge"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/7e4995835f91559f00361b9ad4562cc7f55d3b5fc557cc9a41f9df1ac1e95188/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f726b732f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65"&gt;&lt;img src="https://camo.githubusercontent.com/7e4995835f91559f00361b9ad4562cc7f55d3b5fc557cc9a41f9df1ac1e95188/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f726b732f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65" alt="Forks Badge"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/8ff2a6e5d11d9338d18816c625711a6bb6a4c1d6dacb285f39de224fa9b0eaf4/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f77617463686572732f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65"&gt;&lt;img src="https://camo.githubusercontent.com/8ff2a6e5d11d9338d18816c625711a6bb6a4c1d6dacb285f39de224fa9b0eaf4/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f77617463686572732f65766f6c7574696f6e6172792d6172636869746563747572652f65766f6c7574696f6e6172792d6172636869746563747572652d62792d6578616d706c65" alt="Watchers Badge"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/b28682ede2cbe6b380a0c63bfdfb832dea682f31221eff5b1740fdbd43eae0fd/68747470733a2f2f696d672e736869656c64732e696f2f646973636f72642f31313430323837393731333637363030313438"&gt;&lt;img src="https://camo.githubusercontent.com/b28682ede2cbe6b380a0c63bfdfb832dea682f31221eff5b1740fdbd43eae0fd/68747470733a2f2f696d672e736869656c64732e696f2f646973636f72642f31313430323837393731333637363030313438" alt="Discord Active"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="user-content-objective"&gt;
Objective&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 id="user-content-problem"&gt;
Problem&lt;/h3&gt;
&lt;div&gt;
&lt;p&gt;There are many repositories that describe software and solution architecture in .NET. As there is no single definition of software architecture, they combine several topics:&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Deployment strategies like Modular Monolith and Microservices&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Domain-Driven Design&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Clean, Onion, Hexagonal Architecture&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Infrastructure&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;as if each of the above were the only possible solution. And that is the problem - it is very rare that any single material shows you a concrete decision path or mix…&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/evolutionary-architecture/evolutionary-architecture-by-example"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  What's Inside 🏗️
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;In-depth explorations of various architectural styles&lt;/li&gt;
&lt;li&gt;Real-world examples that vividly depict the context and interactive approach to architectural thinking&lt;/li&gt;
&lt;li&gt;One of architecture evolutionary steps diagrams&lt;/li&gt;
&lt;li&gt;Code samples and comprehensive documentation to help you hit the ground running&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ojtusj69nz5l06t7otu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ojtusj69nz5l06t7otu.png" alt="Image description" width="800" height="841"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our primary goal with this project is not just to showcase architectural styles but to provide you with a comprehensive resource for understanding how architecture can adapt and thrive in the ever-changing landscape of software development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why 'Evolutionary Architecture'? 💡
&lt;/h2&gt;

&lt;p&gt;We firmly believe that architecture should not be a one-size-fits-all concept. Instead, it should evolve and adapt as projects and requirements evolve. Our repository aims to empower developers like you with the knowledge and examples needed to make informed architectural decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  We Want Your Feedback 🤔
&lt;/h2&gt;

&lt;p&gt;We're eager to hear your thoughts, feedback, and contributions. Dive into the repo and let us know what you think! Your input will play a crucial role in shaping the future of this project.&lt;/p&gt;

&lt;p&gt;Feel free to explore, fork, and contribute to the codebase. Your expertise can help make this resource even more valuable to the community.&lt;/p&gt;

&lt;p&gt;Thank you for joining us on this exciting journey into the world of evolutionary architecture. We can't wait to see how it benefits your projects and your understanding of architecture in the .NET ecosystem.&lt;/p&gt;

&lt;p&gt;Stay curious, stay innovative, and happy coding! 🚀&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>🔥Utilizing Feature Flags in Monoliths: A Simple yet Powerful Enhancement for Agility 🚀</title>
      <dc:creator>🧑‍💻 Kamil Bączek</dc:creator>
      <pubDate>Sun, 13 Aug 2023 08:10:29 +0000</pubDate>
      <link>https://forem.com/kamilbaczek/utilizing-feature-flags-in-monoliths-a-simple-yet-powerful-enhancement-for-agility-59n8</link>
      <guid>https://forem.com/kamilbaczek/utilizing-feature-flags-in-monoliths-a-simple-yet-powerful-enhancement-for-agility-59n8</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;📚 Tl;dr&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Feature flags&lt;/strong&gt;: Dynamic switches altering application behavior without code changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advantages in modular monoliths&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Module Management&lt;/strong&gt;: Enable/disable modules based on flags during startup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing and Isolation&lt;/strong&gt;: Independent testing of modules, simplified troubleshooting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scaling with Agility&lt;/strong&gt;: Scale necessary parts based on workload, maintaining cohesion.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transitioning to Microservices&lt;/strong&gt;: Consider when flag-based scalability gets complex; assess pros and cons.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrating in .NET&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Install/register Microsoft NuGet package for easy feature flag handling.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conclusion&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Impact&lt;/strong&gt;: Reshapes modular monoliths for agile development, testing, and scalability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Benefits&lt;/strong&gt;: Enhanced module management, isolated testing, strategic scaling.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;🏆 How Feature Flags enable monolith agility❓❓&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Feature flags, those dynamic conditional switches that can be swiftly altered, have emerged as a game-changer for modern software development. They empower developers to control the behavior of their applications without changing code, facilitating better testing, scalability, and a more agile development process. In this post, let's delve deeper into how feature flags can be a game-changer for modular monolith architectures, and how they can enable efficient module management and enhanced scalability.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;🔗 Dynamic Module Management with Feature Flags&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In the world of modular monoliths, managing and evolving individual modules can be quite challenging. &lt;/p&gt;

&lt;p&gt;This is where feature flags come to the rescue. By utilizing feature flags during application startup, you can dynamically enable or disable modules based on their respective feature flag states. This means that during initialization, you can make decisions on whether to register a particular module's dependencies or skip them entirely. &lt;/p&gt;

&lt;h3&gt;
  
  
  🧪 &lt;strong&gt;Empowering Testing and Isolation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Feature flags play a pivotal role in enhancing your testing strategies. By enabling the isolation of modules, you can test them independently. This not only streamlines the testing process but also reduces the complexities of troubleshooting issues. Your development teams can focus on perfecting one module at a time without having to grapple with intricate dependencies or entangled code, they don’t have to setup configuration from others module and test only public interfaces or message consumers.&lt;/p&gt;

&lt;h3&gt;
  
  
  🌐 &lt;strong&gt;Scaling Strategically with Agility&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Scaling modular monoliths can be a double-edged sword. Transitioning to microservices for the sake of scalability can introduce a slew of operational and architectural complexities.&lt;br&gt;
Feature flags provide an alternative avenue. &lt;/p&gt;

&lt;p&gt;By enabling the dynamic activation of modules, you can selectively scale only the required parts of your application. This approach proves especially powerful when dealing with variable workloads, where some modules might require more resources than others.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F95so47vx5141mxnd4m2k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F95so47vx5141mxnd4m2k.png" alt="Image description" width="800" height="734"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As your project's demands increase, feature flags let you scale the necessary modules while maintaining the overall cohesiveness of your monolith.&lt;/p&gt;
&lt;h3&gt;
  
  
  💡 &lt;strong&gt;When to consider extraction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;While feature flags grant incredible flexibility, there might come a point when scaling via flags becomes cumbersome or leads to a convoluted codebase. If feature flag-based scalability starts to hinder development agility, it might be time to consider transitioning specific modules into microservices. However, this decision should be made judiciously, considering the added complexity and operational overhead associated with microservices architectures.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;🔗 This is really simple!&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Integrating feature flags into a .NET environment is remarkably uncomplicated. Through the installation and registration of the Microsoft NuGet package, you can effortlessly handle feature flag configuration.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;🚀 In Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Feature flags are a dynamic force that can reshape the landscape of modular monoliths. By enabling dynamic control over module activation and deactivation, feature flags pave the way for more agile development, enhanced testing strategies, and strategic scalability. So, whether you're looking to optimize your monolith or cautiously venture into microservices territory, feature flags can be your guiding light toward a more efficient and adaptable software architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow me
&lt;/h2&gt;

&lt;p&gt;🚀 If you're looking for ways to improve your software development skills and stay up to date with the latest trends and best practices, be sure to follow me on dev.to!📚 I regularly share valuable insights and tips on software development, as well as updates on my latest projects.&lt;/p&gt;

&lt;p&gt;Speaking of projects, I'd like to invite you to check out my modular monolith project on GitHub💻, called Estimation Tool. It's a great example of how you can use modularization to build a more scalable and maintainable system. The project is open-source and well-documented, so you can learn by example and see how I applied the concepts of modularization in practice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kamilbaczek/Estimation-Tool"&gt;https://github.com/kamilbaczek/Estimation-Tool&lt;/a&gt; 🔗&lt;/p&gt;

&lt;p&gt;So if you're looking to level up your development skills, be sure to follow me on dev.to and check out my modular monolith project on GitHub. Happy coding!🎉&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>softwaredesign</category>
      <category>architecture</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>🚀 Mastering Modularization: Embracing Simplicity: Simplifying your codebase with Deletion Thinking 🧠</title>
      <dc:creator>🧑‍💻 Kamil Bączek</dc:creator>
      <pubDate>Mon, 19 Jun 2023 05:42:26 +0000</pubDate>
      <link>https://forem.com/kamilbaczek/mastering-modularization-embracing-simplicity-simplifying-your-codebase-with-deletion-thinking-1ogm</link>
      <guid>https://forem.com/kamilbaczek/mastering-modularization-embracing-simplicity-simplifying-your-codebase-with-deletion-thinking-1ogm</guid>
      <description>&lt;p&gt;Improving software design can greatly increase team productivity by allowing developers to refactor easily, propose improvements, and take initiative.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Well-defined interfaces&lt;/strong&gt;  between software modules, such as public classes, methods, endpoints, or events, are crucial for effective communication.&lt;/p&gt;

&lt;p&gt;One way to judge if a software module is well-defined is to  &lt;strong&gt;use deletion thinking&lt;/strong&gt; , which involves evaluating the number of changes required to remove the module and questioning whether all public interfaces are necessary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KdOfZKHk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/05/image-1024x614.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KdOfZKHk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/05/image-1024x614.png" alt="" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EXjhP3vJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/05/image-1-1024x595.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EXjhP3vJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/05/image-1-1024x595.png" alt="" width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NiEZ7E_D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/05/image-2-1024x518.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NiEZ7E_D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/05/image-2-1024x518.png" alt="" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During the design phase, ask yourself: *&lt;em&gt;how many changes will be needed to remove this software piece? *&lt;/em&gt; Then, analyze each change to see if any publicly exposed implementation details can be rearranged to hide the mechanism’s implementation&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Good architecture is not just about building a structure that stands upright. It’s about creating a design that allows you to easily change or remove parts of it as needed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To streamline the process of disabling a module, I like to use feature flags during the module dependencies registration (implementation details registrations). &lt;/p&gt;

&lt;p&gt;By doing so, I can quickly disable a business process or capability.  &lt;strong&gt;Determine the number of feature flags required to disable a module, much like using deletion thinking.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s essential to double-check software design and implementation to ensure it’s robust and efficient. By considering these critical questions during software development, you can create better-designed software.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://artofsoftwaredesign.net/blog/mastering-modularization-deletion-thinking/"&gt;Mastering Modularization: Deletion Thinking&lt;/a&gt; appeared first on &lt;a href="https://artofsoftwaredesign.net"&gt;ArtOfSoftwareDesign&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>modularization</category>
      <category>softwareengineering</category>
      <category>architecture</category>
      <category>softwaredesign</category>
    </item>
    <item>
      <title>📈 Boost Your Integration Testing for REST APIs with Snapshot Testing in .NET</title>
      <dc:creator>🧑‍💻 Kamil Bączek</dc:creator>
      <pubDate>Tue, 11 Apr 2023 14:28:00 +0000</pubDate>
      <link>https://forem.com/kamilbaczek/boost-your-integration-testing-for-rest-apis-with-snapshot-testing-g2b</link>
      <guid>https://forem.com/kamilbaczek/boost-your-integration-testing-for-rest-apis-with-snapshot-testing-g2b</guid>
      <description>&lt;h2&gt;
  
  
  ⚡ &lt;strong&gt;TD:LR&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Tests are crucial for software projects, but they should be easy to maintain.&lt;/li&gt;
&lt;li&gt;Classic assertions can become difficult to maintain when contracts change.&lt;/li&gt;
&lt;li&gt;Snapshot testing is an alternative approach to classic assertions.&lt;/li&gt;
&lt;li&gt;In snapshot testing, the first test result is recorded as a snapshot, and subsequent tests are compared against it.&lt;/li&gt;
&lt;li&gt;Snapshot testing makes it easier to maintain tests as the contract changes.&lt;/li&gt;
&lt;li&gt;The article provides a step-by-step guide to implementing snapshot testing for integration tests.&lt;/li&gt;
&lt;li&gt;Snapshot testing has pros and cons, and it’s important to be aware of its limitations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing is a crucial aspect of any software project 🧪
&lt;/h2&gt;

&lt;p&gt;Tests are necessary to improve and evolve the project. However, with great power comes great responsibility, and tests should be easy to maintain; otherwise, our development process will slow down.&lt;/p&gt;

&lt;p&gt;In this article, we will focus on integration testing, particularly for a REST API endpoint that returns a paginated list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Classic Assertions Problem 🤯
&lt;/h2&gt;

&lt;p&gt;There are several ways to assert the results of an API test, such as hard-coding expected items and asserting one item or hard-coding all items and asserting all items. However, when the API is nested and the contract changes, you will need to rewrite your assertions, and you may need to modify several places.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to make assertions easier to maintain❓
&lt;/h2&gt;

&lt;p&gt;i would like to highlitht snapshot testing approach (another words approval testing).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2CH_MN4A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ytsp0300.pages.labranet.jamk.fi/images/snapshot-testing.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2CH_MN4A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ytsp0300.pages.labranet.jamk.fi/images/snapshot-testing.png" alt="https://ytsp0300.pages.labranet.jamk.fi/images/snapshot-testing.png" width="800" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Approval testing is a different approach to asserting results. In snapshot testing, we execute the test for the first time and record the output as a snapshot. We then compare subsequent test results against this snapshot to ensure that the API is still behaving as expected. This approach makes it easier to maintain tests as the contract changes since we only need to update the snapshot instead of multiple assertions.&lt;/p&gt;

&lt;p&gt;Let’s skip the theory and proceed step by step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step by step Guide 📘
&lt;/h2&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As you can see, these integration tests are quite ordinary except for one particular feature: the classes have an attribute called &lt;strong&gt;[UseVerify]&lt;/strong&gt;. Instead of using traditional assertions, the test results are passed to a function called &lt;strong&gt;Verify()&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Daazot31--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/04/verify.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Daazot31--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/04/verify.png" alt="" width="668" height="130"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To work effectively with snapshot testing, I use the Rider Plugin. (Verify Support)&lt;/p&gt;

&lt;p&gt;Like you can see on digram we are on the state when we never executed a test a we don’t have snapshot. During Verify function execution git diff window opens.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jF1LnTeo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/04/verify_snapshot-1024x595.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jF1LnTeo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/04/verify_snapshot-1024x595.png" alt="" width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am reviewing the results of the tests conducted on my function. Based on the test results, I have the option to approve them as expected or reject them and attempt to fix the test. After making any necessary corrections, I can review and approve the results again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D8CByjtD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/04/snapshot2-1024x647.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D8CByjtD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/04/snapshot2-1024x647.png" alt="" width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After approval, a text file containing the results is created. This is known as a snapshot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Aswq98_e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/04/snapshot3-1024x110.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Aswq98_e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/04/snapshot3-1024x110.png" alt="" width="800" height="86"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, if we broke something and the method doesn’t return a filled list but instead an empty one, the test will fail.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--joJKiV7A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/04/snapshot_4-1024x138.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--joJKiV7A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/04/snapshot_4-1024x138.png" alt="" width="800" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eRVANNBf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/04/snapshot3-3-1024x110.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eRVANNBf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/04/snapshot3-3-1024x110.png" alt="" width="800" height="86"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When adding a property to the contract, a diff will be opened. &lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F76biypsfnssogjgu50ev.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F76biypsfnssogjgu50ev.png" alt="Image description" width="800" height="360"&gt;&lt;/a&gt;&lt;br&gt;
After reviewing the changes, you can approve them if they appear correct.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XNhQdqsF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/04/snapshot_5-1024x110.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XNhQdqsF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/04/snapshot_5-1024x110.png" alt="" width="800" height="86"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although we have made changes to the functionality, the modification of the tests is minimal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Cases 🤔
&lt;/h2&gt;

&lt;p&gt;It may be worth considering the use of approval testing in cases where writing traditional assertions with loops to cover a large amount of data is time-consuming or difficult. This is particularly true when dealing with complex assertions. For example: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;testing the output of a report endpoint,&lt;/li&gt;
&lt;li&gt;parsing results from files &lt;/li&gt;
&lt;li&gt;verifying the results of complex data aggregation endpoints&lt;/li&gt;
&lt;li&gt;apr results that is large or complex data structures, where traditional assertion-based testing may not be practical.&lt;/li&gt;
&lt;li&gt;snapshot testing can be used to verify that database queries it is useful when dealing with complex queries that involve multiple joins and filters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Learn by example 📖
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/kamilbaczek/Product.Inventory/blob/main/ProductInventory.IntegrationsTests/ProductsControllerTests.cs%0A"&gt;Product Inventory Example&lt;br&gt;
&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Trade off analysis 🔖
&lt;/h3&gt;

&lt;h4&gt;
  
  
  👍 Pros:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Snapshot testing makes it easier to maintain tests as the contract changes.&lt;/li&gt;
&lt;li&gt;It reduces the number of assertions required for testing.&lt;/li&gt;
&lt;li&gt;It reduces the complexity of tests and improves readability.&lt;/li&gt;
&lt;li&gt;It allows developers to see the difference between the current test output and the previous one.&lt;/li&gt;
&lt;li&gt;It is more flexible than traditional assertion testing, allowing developers to test a wide range of scenarios with a single snapshot.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  👎 Cons:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;The test results may be invalid if the developer approves them without reviewing them carefully.&lt;/li&gt;
&lt;li&gt;Snapshot testing may not be suitable for testing scenarios that involve randomness or unpredictable outputs.&lt;/li&gt;
&lt;li&gt;It may not be as precise as traditional assertion testing because it only checks if the output has changed, not how it has changed.&lt;/li&gt;
&lt;li&gt;It may require additional tooling or plugins to work effectively, which may add complexity to the testing process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As with most things, there are trade-offs. While I like this technique and agree with its consequences, it is important to be aware of its limitations. &lt;/p&gt;

&lt;h2&gt;
  
  
  Follow me
&lt;/h2&gt;

&lt;p&gt;🚀 If you're looking for ways to improve your software development skills and stay up to date with the latest trends and best practices, be sure to follow me on dev.to!📚 I regularly share valuable insights and tips on software development, as well as updates on my latest projects.&lt;/p&gt;

&lt;p&gt;Speaking of projects, I'd like to invite you to check out my modular monolith project on GitHub💻, called Estimation Tool. It's a great example of how you can use modularization to build a more scalable and maintainable system. The project is open-source and well-documented, so you can learn by example and see how I applied the concepts of modularization in practice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kamilbaczek/Estimation-Tool"&gt;https://github.com/kamilbaczek/Estimation-Tool&lt;/a&gt; 🔗&lt;/p&gt;

&lt;p&gt;So if you're looking to level up your development skills, be sure to follow me on dev.to and check out my modular monolith project on GitHub. Happy coding!🎉&lt;/p&gt;

</description>
      <category>testing</category>
      <category>dotnet</category>
      <category>tutorial</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Types complexity in software systems</title>
      <dc:creator>🧑‍💻 Kamil Bączek</dc:creator>
      <pubDate>Fri, 27 Jan 2023 19:26:14 +0000</pubDate>
      <link>https://forem.com/kamilbaczek/types-complexity-in-software-systems-4gb8</link>
      <guid>https://forem.com/kamilbaczek/types-complexity-in-software-systems-4gb8</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kKbRUioK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/01/frustrated-1024x416.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kKbRUioK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://artofsoftwaredesign.net/wp-content/uploads/2023/01/frustrated-1024x416.webp" alt="" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are different types of complexity in the IT system. Understanding the types of complexities we face will help us make better design and architectural decisions. Adapt techniques to the problems we want to solve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Domain complexity
&lt;/h2&gt;

&lt;p&gt;Domain complexity, as the name suggests, is the complexity of the business problem that a given system is to solve. For example, we create a system in which you can insure real estate. Realty arrangements have many conditions that only insurers know. A programmer who was not previously involved in the insurance industry will be initially overwhelmed with the number of dependency rules and terminology applicable in this industry.&lt;/p&gt;

&lt;p&gt;Failure to deal with this type of complexity causes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High Coupling&lt;/li&gt;
&lt;li&gt;Overengeering&lt;/li&gt;
&lt;li&gt;Team member rotation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Failure to understand the domain often results in the fact that even a greenfield project quickly becomes hard to maintain.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to fight with domain complexity?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r0U4p5w---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.ctfassets.net/jkeue23vfil0/32KRGlKERi9SF4TyiumgI/b83b381e6c2fea879ab938ea8a04c470/group-of-diverse-people-having-a-business-meeting.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r0U4p5w---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.ctfassets.net/jkeue23vfil0/32KRGlKERi9SF4TyiumgI/b83b381e6c2fea879ab938ea8a04c470/group-of-diverse-people-having-a-business-meeting.jpg" alt="meeting" width="800" height="438"&gt;&lt;/a&gt; A set of proven techniques in battle is Domain Driven Design described by Eric Evans. Strategic patterns are especially noteworthy because they provide tools on how to communicate with people from business. It allows us to gain knowledge about business processes. Extract the core of the system. Finding a shallow and deep places in system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accidencal complexity
&lt;/h2&gt;

&lt;p&gt;Random sensitivity is present in every IT system. It is especially visible in the legacy in systems. Each of us probably had a simple task to do. For example, add one field to the UI. We evaluate such tasks for one manday. We go to the place in the code where we have to add this field. It turns out that the code is incomprehensible and operates on reflection and dynamic types. Somehow we managed to do it in one manday. The next day, the tester tells us that we’ve broken something elsewhere. Combination and repair takes another mandays two days. We are finally done with the tasks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U--9ttK5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.ctfassets.net/jkeue23vfil0/4k1pS3j36fZ0AdvbQPAwzJ/fcad01ed6045d09202f21abca2f3d04b/4edbbd50-d156-407f-9e34-f2c75763bf53.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U--9ttK5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.ctfassets.net/jkeue23vfil0/4k1pS3j36fZ0AdvbQPAwzJ/fcad01ed6045d09202f21abca2f3d04b/4edbbd50-d156-407f-9e34-f2c75763bf53.webp" alt="accidental complexity" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Accidental complexity contributed to not deliver task on time.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to fight Accidencal complexity?
&lt;/h2&gt;

&lt;p&gt;We should fight against accidental complexity first of all with Refactoring. In line with the “Scout Boy” rule. If we go into some code we become the better one. In the future there will be an entry on “Countinous Refactoring” where this topic will be more relevant. Another tool to combat this type of complexity is abstraction. Sometimes a good technique is to cut yourself off the legacy code with create new module. In this new module we will create new code in good way. For the old legacy code we will create abstraction and use this abstraction in our new module.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Each IT project is different, in some we have a complex domain, and in another problem is randomness. Sometimes we have both. We already know that we can fight a complex domain with Domain Driven Design. In case of accidental complexity we use modularity and refactoring. It is worth educating your knowledge in those topics. Introducing the discussed elements to your project so that the business earns more and the developers have a more pleasant work.&lt;/p&gt;

</description>
      <category>domaindrivendesign</category>
      <category>modularization</category>
    </item>
    <item>
      <title>👮 Architecture Governance: Keeping Your System's Design on Track with Continuous Arch Testing</title>
      <dc:creator>🧑‍💻 Kamil Bączek</dc:creator>
      <pubDate>Sun, 22 Jan 2023 23:00:00 +0000</pubDate>
      <link>https://forem.com/kamilbaczek/architecture-governance-keeping-your-systems-design-on-track-with-continuous-arch-testing-4k4k</link>
      <guid>https://forem.com/kamilbaczek/architecture-governance-keeping-your-systems-design-on-track-with-continuous-arch-testing-4k4k</guid>
      <description>&lt;h2&gt;
  
  
  📚 Tl;dr
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Architecture governance is a system for maintaining consistency and quality in architectural decisions throughout the development process of a software project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It involves having control over architectural rules and guidelines and ensuring they are adhered to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fitness function is an important component of architecture governance which acts as a "cop" to ensure developers don't break established architectural rules and measures the alignment of the software architecture with business goals.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NetArchTest is a tool that can be used to implement the automatic fitness function by writing unit tests that check dependencies between packages, classes, and methods in the codebase.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📐 What is architecture governance?
&lt;/h2&gt;

&lt;p&gt;When building software projects, there are many architectural decisions that need to be made. It is important to maintain consistency in these decisions to ensure the overall quality and maintainability of the project.&lt;/p&gt;

&lt;p&gt;Having a system for architecture governance allows the team to have control over the architectural rules and guidelines, and to ensure that they are being adhered to throughout the development process. This can help to ensure that the project remains on track, and that any issues or inconsistencies are identified and addressed in a timely manner.&lt;/p&gt;

&lt;p&gt;Additionally, having a well-defined architecture governance system can facilitate collaboration and communication among team members and help to ensure that everyone is working towards the same goals. This can lead to a more cohesive team and a better end product.&lt;/p&gt;

&lt;p&gt;It's also important to note that architecture governance is not a one time process, but a continuous one that adapts to the changes of the project and the organization. That way, the team can ensure that the software architecture is aligned with the business goals and the evolving requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  👮 Fitness function
&lt;/h2&gt;

&lt;p&gt;Fitness function is a way to measure the alignment between the software architecture and the business goals. &lt;/p&gt;

&lt;p&gt;One approach to implementing a fitness function is through the use of automatic fitness functions. Automatic fitness function will be in our case units that will check the validity of architecture decisions. &lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 NetArchTest comes to play
&lt;/h2&gt;

&lt;p&gt;NetArchTest is a library that can be used to write such tests (automatic fitness functions), it allows to check the architecture and ensure that it adheres to predefined rules and constraints.&lt;/p&gt;

&lt;p&gt;With NetArchTest, developers can write unit tests that check the dependencies between different packages, classes, and methods in their codebase. This can be useful for checking that the architecture adheres to principles such as separation of concerns and the single responsibility principle. By running these tests regularly, developers can ensure that the architecture remains consistent and that any changes to the codebase do not violate the predefined rules. ADR and Arch unit test is amazing mix that will help you keep consistant great design.&lt;/p&gt;

&lt;h2&gt;
  
  
  📐 Example 1️⃣
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ADR 1: Creating a Custom Shared Logging NuGet Package for Improved Performance and Maintainability.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Status
&lt;/h4&gt;

&lt;p&gt;Approved&lt;/p&gt;

&lt;h4&gt;
  
  
  Context
&lt;/h4&gt;

&lt;p&gt;We have identified that the current using the Microsoft ILogger interface does not provide optimal memory efficiency and there is inconsistent code optimization across our solution. This can lead to performance issues within our codebase. Additionally, having a consistent logging implementation across the solution will make it more maintainable and easier to understand.&lt;/p&gt;

&lt;h4&gt;
  
  
  Decision
&lt;/h4&gt;

&lt;p&gt;We have decided to develop a custom shared logging NuGet package with “IOptimizedLogging” interface to improve the efficiency of our logging system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consequences
&lt;/h3&gt;

&lt;h4&gt;
  
  
  👍 Pros:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Improved memory efficiency: The custom shared logging NuGet package will improve the memory efficiency of the logging system, as the optimized implementation will be used consistently throughout the solution.&lt;/li&gt;
&lt;li&gt;Improved performance: The package will also improve the performance of the logging system, as the code that optimizes log execution will be consistently implemented throughout the solution.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  👎 Cons:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Increased development and maintenance effort: The development of a custom shared logging NuGet package will require additional resources and effort, including the development and testing of the package, as well as its ongoing maintenance and updates.&lt;/li&gt;
&lt;li&gt;Each new developer or current one has to know that he must use

&lt;code&gt;IOptimizedLogger&lt;/code&gt;

instead

&lt;code&gt;ILogger&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  👮 Fitness Function
&lt;/h3&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;





&lt;h2&gt;
  
  
  📐 Example 2️⃣
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ADR 2: Notifications module should be decupled by events
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Status
&lt;/h4&gt;

&lt;p&gt;Approved&lt;/p&gt;

&lt;h4&gt;
  
  
  Context
&lt;/h4&gt;

&lt;p&gt;The team has determined that the current design of the notifications modules, which relies on coupling via interfaces, is not flexible enough to allow for easy integration with other modules.&lt;/p&gt;

&lt;h4&gt;
  
  
  Decision
&lt;/h4&gt;

&lt;p&gt;The decision is to decouple the notifications modules by using events as the only method of integration, where other modules can publish integration events can be consumed by the notifications modules &lt;code&gt;event handlers&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consequences
&lt;/h3&gt;

&lt;h4&gt;
  
  
  👍 Pros:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Increased flexibility in the overall system design&lt;/li&gt;
&lt;li&gt;Easier integration with other modules&lt;/li&gt;
&lt;li&gt;Improved maintainability of the codebase&lt;/li&gt;
&lt;li&gt;Reduced dependencies between modules&lt;/li&gt;
&lt;li&gt;Cons of decoupling notifications modules by using events:&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  👎 Cons:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Additional complexity in the codebase&lt;/li&gt;
&lt;li&gt;Additional overhead of managing events and event listeners&lt;/li&gt;
&lt;li&gt;The need to re-architect the current notifications modules&lt;/li&gt;
&lt;li&gt;More difficult to debug and troubleshoot if there are issues with the event-based communication.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  👮 Fitness Function
&lt;/h2&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  📚 Description
&lt;/h2&gt;

&lt;p&gt;Checks that any interfaces or class from notifications modules is used in other modules. This checks compliance with a predetermined ADR to avoid coupling via interfaces in the notification module. It is used as a means of ensuring that the code base complies with this ADR and that new developers do not introduce violations of this decision by their lack of knowledge.&lt;/p&gt;




&lt;h2&gt;
  
  
  👮 Fitness Function
&lt;/h2&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  📚 Description
&lt;/h2&gt;

&lt;p&gt;This function verifies that the notification module has event handlers that only consume integration events. It is used to ensure that the notification module adheres to an architectural decision (ADR) that specified that the module should be integrated with other modules through events. The function is checking that this design decision is being followed.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏁 Summary
&lt;/h2&gt;

&lt;p&gt;Architecture governance is a system for maintaining consistency and quality in architectural decisions throughout the development process of a software project.&lt;/p&gt;

&lt;p&gt;It involves having control over architectural rules and guidelines, and ensuring they are adhered to. It also promotes collaboration and communication among team members, and helps to align the software architecture with business goals and evolving requirements.&lt;/p&gt;

&lt;p&gt;A key component of architecture governance is the use of a fitness function, which acts as a "cop" to ensure that developers do not break established architectural rules and measures the alignment of the software architecture with business goals. One way to implement this is through automatic fitness functions, such as using NetArchTest, a library for writing unit tests that check dependencies between packages, classes, and methods in the codebase to ensure adherence to predefined rules and principles such as separation of concerns and the single responsibility principle.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.oreilly.com/library/view/software-architecture-the/9781492086888/"&gt;Software Architecture: The Hard Parts Book&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kgrzybek/modular-monolith-with-ddd"&gt;Kamil Grzybek Modular Monolith has arch tests examples&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=aq8XTTxoslE"&gt;Architecture Fitness Functions Talk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/BenMorris/NetArchTest"&gt;NetArchTest Project&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🤝🏻 Follow me
&lt;/h2&gt;

&lt;p&gt;🚀 If you're looking for ways to improve your software development skills and stay up to date with the latest trends and best practices, be sure to follow me on dev.to!📚 I regularly share valuable insights and tips on software development, as well as updates on my latest projects.&lt;/p&gt;

&lt;p&gt;Speaking of projects, I'd like to invite you to check out my modular monolith project on GitHub💻, called Estimation Tool. It's a great example of how you can use modularization to build a more scalable and maintainable system. The project is open-source and well-documented, so you can learn by example and see how I applied the concepts of modularization in practice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kamilbaczek/Estimation-Tool"&gt;https://github.com/kamilbaczek/Estimation-Tool&lt;/a&gt; 🔗&lt;/p&gt;

&lt;p&gt;So if you're looking to level up your development skills, be sure to follow me on dev.to and check out my modular monolith project on GitHub. Happy coding!🎉&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>dotnet</category>
      <category>csharp</category>
      <category>codequality</category>
    </item>
    <item>
      <title>🔧 Mastering Modularization: A Beginner's Guide to Organizing Complex Software Systems</title>
      <dc:creator>🧑‍💻 Kamil Bączek</dc:creator>
      <pubDate>Fri, 13 Jan 2023 18:17:56 +0000</pubDate>
      <link>https://forem.com/kamilbaczek/mastering-modularization-a-beginners-guide-to-organizing-complex-software-systems-80g</link>
      <guid>https://forem.com/kamilbaczek/mastering-modularization-a-beginners-guide-to-organizing-complex-software-systems-80g</guid>
      <description>&lt;h1&gt;
  
  
   ⚡ Tl;dr
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Modularization is a method of dividing complex systems into smaller, manageable parts for better management and understanding.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It improves the efficiency, reliability, and maintainability of software projects by organizing code into modules.&lt;br&gt;
It reduces cognitive load for developers by decreasing the amount of information they need to process at one time, making complex systems easier to understand and preventing burnout.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modules in software development can be thought of as building blocks, like lego pieces.&lt;br&gt;
Each module has a unique set of public interfaces, data structures or messages that act as contracts for other developers to use.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When working with modules, it's important to treat them as black boxes and only interact with them through their defined public interfaces to avoid coupling and improve the modularity of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In .NET, a module is a self-contained piece of code that serves a specific purpose or function and can be imported and used in other pieces of code.&lt;br&gt;
Assemblies are used to group code in .NET because they allow for a higher level of encapsulation (using internal access), which allows developers to control the level of access other code has to the members of a type and helps to protect the implementation details of a type or member.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To make implementation visible for test, you can use  attribute in the csproj file and specify the test project assembly name.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧩 Why Developers Neglect Modularization?
&lt;/h2&gt;

&lt;p&gt;One reason developers may not prioritize modularization is a lack of knowledge on the subject. Developers often learn languages and frameworks from documentation, which may not emphasize best practices for organizing code and creating modules.&lt;/p&gt;

&lt;p&gt;🤷‍♂️ Another factor may be a lack of understanding about business processes and system domain, which can lead to unrelated pieces of code being closely tied together.&lt;/p&gt;

&lt;p&gt;🤔 Additionally, developers may focus too much on technologies and frameworks that help them build a project quickly, rather than considering business processes and connections between them.&lt;/p&gt;

&lt;p&gt;😟 Poor design and a lack of modularization can lead to the need for a project to be completely rewritten, while using certain frameworks or technologies may not necessarily have the same impact.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Why is modularization considered so valuable in software development?
&lt;/h2&gt;

&lt;p&gt;Modularization 🧩 is a method of dividing complex systems into smaller, manageable parts for better management and understanding. It is based on the principle of "divide and conquer" and improves the efficiency, reliability, and maintainability 🔧 of software projects by organizing code into modules. &lt;/p&gt;

&lt;p&gt;It also reduces cognitive load 🧠 for developers by decreasing the amount of information they need to process at one time, making complex systems easier to understand and preventing burnout 💀.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧱The Lego Principle: Use Modules as the Building Blocks of Your Software Systems
&lt;/h2&gt;

&lt;p&gt;Modules in software development can be thought of as building blocks, like lego pieces. Each module has a unique set of public interfaces, data structures or messages that act as contracts for other developers to use. When working with modules, it's important to treat them as black boxes and only interact with them through their defined public interfaces. This helps to avoid coupling and improve the modularity of the system.&lt;/p&gt;

&lt;p&gt;One common mistake I've seen in projects is when all classes are &lt;code&gt;made public&lt;/code&gt;, which means modularization doesn't exist. Everything is touchable and can be coupled with any other element, leading to a fast path to a "big ball of mud" 💩💩 that we want to avoid 🙅‍♂️.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmg6z9blqysyfifzwzzt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmg6z9blqysyfifzwzzt.png" alt="big ball of mud examples"&gt;&lt;/a&gt;&lt;br&gt;
High coupling module example. Avoid it !!!&lt;/p&gt;

&lt;p&gt;To prevent this, it's key to use the &lt;code&gt;internal&lt;/code&gt; access modifier 🔒 and only expose a clean, well-defined API using public interfaces  and data structures that are easy to consume. Test-driven development (TDD) 🧪 can also help with this, as the first consumer of your module will be yourself. By following these practices, you can create a modular system that is easy to understand, maintain, and extend.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧱 Module Example in .NET
&lt;/h2&gt;

&lt;p&gt;A module is a self-contained piece of code that serves a specific purpose or function, and can be imported and used in other pieces of code. It helps to organize and make code more reusable, and is often used in software development to break up large projects into smaller, more manageable pieces.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤖 Module in .NET
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Module is single Assembly or set of assemblies grouped by &lt;code&gt;Solution Folder&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqo4gktslh94k41sssno.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqo4gktslh94k41sssno.png" alt="Modules view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Divstack Estimation Tool - Emails module view&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Divstack.Company.Estimation.Tool.Emails.Core&lt;/code&gt; is example of sub module of Emails Module. This module gives technical capability to sending Emails. Purpose is to be reusable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why assemblies are used to group code? Why not dictionary?
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Divstack.Company.Estimation.Tool.Emails.Core&lt;/code&gt; assembly is an example of a submodule of the Emails module that provides the technical capability for sending emails. It is designed to be reusable.&lt;/p&gt;

&lt;p&gt;One reason for using assemblies to group code is that they allow for a higher level of encapsulation. Access modifiers such as &lt;code&gt;internal&lt;/code&gt; and &lt;code&gt;public&lt;/code&gt; allow developers to control the level of access other code has to the members of a type, which helps to protect the implementation details of a type or member.&lt;/p&gt;

&lt;p&gt;In contrast, using a dictionary approach &lt;strong&gt;would not allow for the same level of encapsulation&lt;/strong&gt;, as it would not support access modifiers and would always provide access to the class.&lt;/p&gt;

&lt;h3&gt;
  
  
  💪🏼 Let’s go to example
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwv7ecky7gdpclljzd7i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwv7ecky7gdpclljzd7i.png" alt="csharp module view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this module there is only two &lt;code&gt;public&lt;/code&gt; classes.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IEmailSender&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailCoreModule&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="nf"&gt;AddCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IEmailSender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EmailSender&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
        &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IMailConfiguration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MailConfiguration&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
        &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IMailTemplateReader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MailTemplateReader&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Other classes are implementation details&lt;/p&gt;

&lt;p&gt;A module is like a black box for other developers. They only have access to the interface provided by the module, and don't need to worry about how it is implemented. This can be either a service like SendGrid or a standard SMTP server. The advantage of this approach is that it doesn't matter how the module is implemented, as long as it provides the expected functionality through the interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  📦 The Power of the Black Box Approach
&lt;/h3&gt;

&lt;p&gt;A public API should be stable, meaning that it should not change frequently or unexpectedly. It is important for the developer to carefully design the interface of the API to make it easy to understand and use 🧑‍💼. This is similar to the importance of designing a pure REST API. One way to ensure that the API is developer-friendly is to use unit testing 🧪, as tests can serve as the first "client" of the code 💻. That is why it is often recommended to use a technique called Test-Driven Development (TDD) 🧑‍💻, in which tests are written before the implementation code. By writing tests first 🧑‍🔬, the developer can focus on designing a clean and easy-to-use interface for the API.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔧 How to test encapsulated module implementation?
&lt;/h2&gt;

&lt;p&gt;A common problem with understanding unit tests is understanding the word 'Unit'. In our modules, we will have a &lt;code&gt;public&lt;/code&gt; interfaces. In our unit tests, we will be testing the implementation of the interface whose has &lt;code&gt;public&lt;/code&gt; access modifier.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IEmailSender&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailSender&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IEmailSender&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;EmailType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"text/html"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IBackgroundProcessQueue&lt;/span&gt; &lt;span class="n"&gt;_backgroundProcessQueue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IMailConfiguration&lt;/span&gt; &lt;span class="n"&gt;_mailConfiguration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;EmailSender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IMailConfiguration&lt;/span&gt; &lt;span class="n"&gt;mailConfiguration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IBackgroundProcessQueue&lt;/span&gt; &lt;span class="n"&gt;backgroundProcessQueue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_mailConfiguration&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mailConfiguration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;_backgroundProcessQueue&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;backgroundProcessQueue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_mailConfiguration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MailFrom&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_backgroundProcessQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Enqueue&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;SendMessageAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;SendMessageAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SendGridClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_mailConfiguration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApiKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;BuildMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendEmailAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;SendGridMessage&lt;/span&gt; &lt;span class="nf"&gt;BuildMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SendGridMessage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EmailType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fromEmailAddress&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;EmailAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_mailConfiguration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MailFrom&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fromEmailAddress&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetSubject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To make it visible for test project we have to add this code to Divstack.Company.Estimation.Tool.Emails.Core.csproj file.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;&amp;lt;ItemGroup&amp;gt;&lt;br&gt;
    &amp;lt;InternalsVisibleTo Include="Divstack.Company.Estimation.Tool.Emails.Core.UnitTests" /&amp;gt;&lt;br&gt;
  &amp;lt;/ItemGroup&amp;gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  🔖 Summary&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;It is important to note that modularization is a powerful technique that can help improve the overall quality of your code and make it more maintainable and testable. With the proper use of the internal access modifier and following best practices, developers can create a modular system that is easy to understand, maintain, and extend.&lt;/p&gt;

&lt;p&gt;This was a basic introduction to modularization in .NET. In the future, more information will be provided on topics such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Module extraction&lt;/li&gt;
&lt;li&gt;Module definition heuristics&lt;/li&gt;
&lt;li&gt;Modular monolith architecture&lt;/li&gt;
&lt;li&gt;Feature slices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This series will be continued..&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/kamilbaczek/Estimation-Tool" rel="noopener noreferrer"&gt;Modular project example - Estimation Tool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.kamilgrzybek.com/tag/modular-monolith" rel="noopener noreferrer"&gt;A lot of information about modularization with project example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ILBX9fa9aJo" rel="noopener noreferrer"&gt;Great talk about hermetization and architecture that inspired me to start designing systems in modular way&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devmentors.io/courses/modular-monolith" rel="noopener noreferrer"&gt;Courses and materials about modularization DevMentors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=-FaXMV2-k64" rel="noopener noreferrer"&gt;My talk about modular monolith&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Follow me
&lt;/h2&gt;

&lt;p&gt;🚀 If you're looking for ways to improve your software development skills and stay up to date with the latest trends and best practices, be sure to follow me on dev.to!📚 I regularly share valuable insights and tips on software development, as well as updates on my latest projects.&lt;/p&gt;

&lt;p&gt;Speaking of projects, I'd like to invite you to check out my modular monolith project on GitHub💻, called Estimation Tool. It's a great example of how you can use modularization to build a more scalable and maintainable system. The project is open-source and well-documented, so you can learn by example and see how I applied the concepts of modularization in practice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kamilbaczek/Estimation-Tool" rel="noopener noreferrer"&gt;https://github.com/kamilbaczek/Estimation-Tool&lt;/a&gt; 🔗&lt;/p&gt;

&lt;p&gt;So if you're looking to level up your development skills, be sure to follow me on dev.to and check out my modular monolith project on GitHub. Happy coding!🎉&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>dotnet</category>
      <category>softwaredesign</category>
      <category>modularization</category>
    </item>
    <item>
      <title>Why Integration Tests are 'must have' to deliver high quality software?</title>
      <dc:creator>🧑‍💻 Kamil Bączek</dc:creator>
      <pubDate>Tue, 20 Dec 2022 07:18:26 +0000</pubDate>
      <link>https://forem.com/kamilbaczek/why-integration-tests-are-must-have-to-deliver-high-quality-software-10i2</link>
      <guid>https://forem.com/kamilbaczek/why-integration-tests-are-must-have-to-deliver-high-quality-software-10i2</guid>
      <description>&lt;p&gt;Testing is a very important part of the SDLC. Sometimes I've seen projects where there are only unit tests, omitting integration tests. &lt;/p&gt;

&lt;p&gt;When I asked the development teams why they weren't there, I got different answers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have a good coverage of unit tests, that's enough&lt;/li&gt;
&lt;li&gt;We had these tests but they were flaky, so we don't develop them&lt;/li&gt;
&lt;li&gt;Its hard to write first test and we have no time now to write them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fruvw8v2t5916te623wef.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fruvw8v2t5916te623wef.jpg" alt="issue on production" width="418" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Good unit test coverage is not enough in most cases. &lt;/p&gt;

&lt;h3&gt;
  
  
  Why?
&lt;/h3&gt;

&lt;p&gt;Unit tests provide certainty in Core places where we have business rules. &lt;/p&gt;

&lt;p&gt;They ensure us that logic and calculation works as expected. They cannot check integration between components because they are work in isolation.&lt;/p&gt;

&lt;p&gt;Integrations tests can ensure integration of components work properly. In addition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;serialization&lt;/li&gt;
&lt;li&gt;dependency injection registration&lt;/li&gt;
&lt;li&gt;database configuration&lt;/li&gt;
&lt;li&gt;data persistance&lt;/li&gt;
&lt;li&gt;schema migrations&lt;/li&gt;
&lt;li&gt;http clients
etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Without integrations tests we are not enough confident to put our code to production, without manual regression tests. That makes real CI/CD impossible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;According to test pyramid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3a901pgf97abum39qb6b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3a901pgf97abum39qb6b.png" alt="Image description" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would use suggest a lot of unit tests where we have logic + a few integration tests to cover e.g happy path with one variant of logic and negative path.&lt;/p&gt;

&lt;p&gt;If there is no logic i will write only integrations tests. &lt;/p&gt;

&lt;p&gt;There are many ready-made libraries that make our lives easier.&lt;/p&gt;

&lt;p&gt;For example, WireMock can be used to mock responses from the external systems that we are integrating with.&lt;/p&gt;

&lt;p&gt;When we use events for integration we can use queue simulator and simulate event publishing. Test our whole module in isolation. &lt;/p&gt;

&lt;p&gt;To sum up, Unit test can check logic but won't tell us that application behaves correctly. Unit Test with Integration tests can do it. With such a combination plugged into CI/CD pipeline you and your team should be pretty confident when you release new version of your code. First test can be difficult to write but it's is worth it. If your team will embrace the speed of implementations and thus the quality of the code will increase significantly.&lt;/p&gt;

</description>
      <category>ci</category>
      <category>testing</category>
      <category>automation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Clean Unit Testing Part II - Give a context for your 'Arrange ' test body part</title>
      <dc:creator>🧑‍💻 Kamil Bączek</dc:creator>
      <pubDate>Fri, 04 Nov 2022 06:37:33 +0000</pubDate>
      <link>https://forem.com/kamilbaczek/clean-unit-testing-part-ii-give-a-context-for-your-arrange-test-body-part-117p</link>
      <guid>https://forem.com/kamilbaczek/clean-unit-testing-part-ii-give-a-context-for-your-arrange-test-body-part-117p</guid>
      <description>&lt;p&gt;I've seen many times that &lt;strong&gt;unit tests were hard to read and maintain&lt;/strong&gt;. The Tests in which the preparation of the test did not fit on the monitor. The different parts of the test were mixed and obfuscated. Unit tests have to be clear and easy to maintain to bring us value.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Good programmers write code that humans can understand - M. Fowler (1999)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think this quote tells us that we should focus on naming things, continuously refactoring and creating a class that has a single responsibility. The same rules we should apply to unit testing.&lt;/p&gt;

&lt;p&gt;I want to give you a few pieces of advice on how we can write cleaner tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's go to examples
&lt;/h2&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Our goal is to make sure when the user password is the expired application will generate a reset password token.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bad Tests
&lt;/h2&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We have many mock setups. In this, the &lt;strong&gt;arrangement part of the test is huge&lt;/strong&gt;. This is a major issue that I've seen. At first glance, it’s hard to locate the method that we are testing. We have some hard-coded test data. The data format is not close to real data. This code is not easy to read for a human to understand what we are testing and how we are testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lets fix it.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fakers
&lt;/h3&gt;

&lt;p&gt;The first thing we’ll do in our refactoring is getting rid of creating objects for testing in a non-elegant way. We will get rid of magic strings. We can extract the creation of objects like SignInCommand or UserAccount to static classes with a factory method. Test data to create these objects, we can use the Faker.NET library which gives the possibility to interfere with fake mail, phone number, first name etc.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As we can see in UserAccountFaker class. We have used Faker.NET to generate a fake email and first name. Generated that is closer to real compared to some ‘testtest’ phrases.&lt;/p&gt;

&lt;p&gt;Then we used this faker in line 41.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mock Setups
&lt;/h3&gt;

&lt;p&gt;For me, mocking framework API not looks good. It is easy to lose context here and obfuscate test code. To improve readability and give context to the code the same as is in production code in tests we can use private methods. By creating a private method you can give a meaning-full name for this mock setup e.g&lt;br&gt;
"TimePassage". Please compare the Good and Bad test examples now. I'm sure that you can see the difference in readability, cognitive load is lower.&lt;/p&gt;

&lt;p&gt;A lot of private methods on the bottom of the file do not look good to me. How do I handle this? I will explain this in the next post from this series.&lt;/p&gt;

&lt;h3&gt;
  
  
  COUNTER ARGUMENTS
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Writing each test in that way will take too much time.&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Answer:&lt;/strong&gt;&lt;br&gt;
Using IDE you can extract classes, and methods, and create factory methods in seconds. I recommend that you familiarize yourself with the keyboard shortcuts and the capabilities of IDE Rider or Visual Studio + Resharper.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I would prefer to see all code on one screen not hiding implementations of mocks or fakers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Answer:&lt;/strong&gt;&lt;br&gt;
The human brain can take a certain dose of information at a time, if the preparation of the test is too complicated it will be difficult for you to understand at a glance. You will have to read it multiple times to understand how it works. Which will drastically affect productivity. In my opinion, it is better to divide the code into smaller fragments and when we are curious about the implementation or suspect a bug, it enters the private method to see something in it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;In summary, by extracting data preparation to Fakers and naming setup mocks. We improve readability and understanding of unit testing. This is a bit of pragmatic advice that can be implemented in any project at any time. &lt;/p&gt;

&lt;p&gt;Take care of your cognitive load and productivity. See you on the next article 💪💪💪&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>cleancode</category>
      <category>refactorit</category>
      <category>codequality</category>
    </item>
  </channel>
</rss>
