<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Chris Fryer on Medium]]></title>
        <description><![CDATA[Stories by Chris Fryer on Medium]]></description>
        <link>https://medium.com/@cfryerdev?source=rss-ef7825d5c6e0------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*Qcv_9IZIkMxKPMJbHR5-uA.png</url>
            <title>Stories by Chris Fryer on Medium</title>
            <link>https://medium.com/@cfryerdev?source=rss-ef7825d5c6e0------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 03 Jun 2026 06:17:49 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@cfryerdev/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Summary: Module Federation Architecture (MFA/MFE)]]></title>
            <link>https://medium.com/@cfryerdev/summary-module-federation-architecture-mfa-mfe-a411a289e670?source=rss-ef7825d5c6e0------2</link>
            <guid isPermaLink="false">https://medium.com/p/a411a289e670</guid>
            <category><![CDATA[micro-frontends]]></category>
            <category><![CDATA[module-federation]]></category>
            <category><![CDATA[react-microfrontend]]></category>
            <dc:creator><![CDATA[Chris Fryer]]></dc:creator>
            <pubDate>Tue, 25 Mar 2025 23:33:58 GMT</pubDate>
            <atom:updated>2025-03-25T23:33:58.319Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*3HeSwWba3naO_o9n" /><figcaption>Photo by <a href="https://unsplash.com/@therealcaique?utm_source=medium&amp;utm_medium=referral">Caique Morais</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p><em>Note: The contents of this article are my opinions, not the views or opinions of my employer or other entity. Please feel free to give it a clap, it helps!</em></p><h3>What are Microfrontends?</h3><p>Microfrontend architecture is an approach to breaking up your front-end into a set of independently deploy-able, loosely coupled applications and/or components. These applications are then assembled together to act as a single user experience, once deployed.</p><p>These applications tend to closely mirror a corresponding micro-service architecture as well, but its not always the case. I fully expect to see Frontend Architects who specialize in this pattern in the near future.</p><p>A lot of folks have talked about this term over the years, so allow me to show you my favorite:</p><blockquote><strong>Martin Fowler — Microfrontends</strong><br><a href="https://martinfowler.com/articles/micro-frontends.html">https://martinfowler.com/articles/micro-frontends.html</a></blockquote><h3>The history of microfrontend implementations.</h3><p>In the interest of easy to digest information, I will touch on only the top three microfrontend implementations that I personally have used.</p><ul><li><strong>Hybrid: </strong>This is the common one most people think about when somebody mentioned Microfrontends. This is the pattern of ejecting individual components as js modules and combining them all in one page or application. These modules do not even need to be the same framework, you can mix and match angular, react, vue, and vanilla js.</li><li><strong>Distributed/Microsites</strong>: One of the less adopted patterns, that share similar structures such as Distributed Frontends. Without going into too much detail, this is the act of writing many small isolated standalone web applications and using infrastructure to tie them together to appear to be one single application experience. I am currently writing an article about this as well, but it has far more pitfalls to consider.</li><li><strong>Module Federation: </strong>Module Federation (MF) is a feature that allows for the dynamic loading of multiple versions of a module from multiple independent build systems. This allows for multiple systems to share code and be dynamically updated without having to rebuild the entire application. It also enables distributed teams and applications with different release cycles to share code without needing to wait for all systems to agree to and deploy a single shared version of a module.</li></ul><h3>What is Module Federation?</h3><p>When we talk Microfrontends, we generally need to load applications individually asynchronously only when requested. We do this by using a feature known as Module Federation to create a single deploy-able artifact of an application, which can be loaded on demand.</p><p>We will get deeper into Module Federation a bit later in the article, but for now, a summary will help you stay on track.</p><p>More Information: <a href="https://webpack.js.org/concepts/module-federation/">Documentation</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aLo__iUf8pzLwWdMP1TllA.jpeg" /></figure><h3>Module Federation Frameworks</h3><p>There are a handful of frameworks and technologies that are attempting to get into Module Federation such as:</p><ul><li><strong>Webpack Module Federation:</strong> <a href="https://webpack.js.org/concepts/module-federation/">Documentation</a> This is the standard in my opinion and the one with the most flexibility and development activity.</li><li><strong>Vite/Rollup:</strong> <a href="https://github.com/originjs/vite-plugin-federation">Documentation</a> Inspired by Webpack and compatible with Webpack Module Federation.</li></ul><p><strong><em>Special Note:</em></strong><em> I want it to be clear, not all of these support all the variations of loading federated modules such as Dynamic Remotes. (See below)</em></p><h3>Alright, so lets talk terms..</h3><p>As you adopt Module Federation, there are a handful of terms you need to become comfortable with and where/when to use them.</p><ul><li><strong>Hosts: </strong>A host is a simple parent application, which is put together during build-time or run-time from many smaller applications known as Remotes.</li><li><strong>Remotes:</strong> Remotes are easy, they are essentially single page applications, which are minified, bundled, and exported as javascript modules. They are wrapped in a Webpack shim, allowing a Host to know how to load and use them, and are essentially portable modules which can be used across Hosts or even by other Remotes!</li><li><strong>Modules: </strong>These are the parts that a Remote exposes for use inside a host or other remotes. This usually equates to components but not always!</li></ul><h3>We have different ways to federate remotes too!</h3><p>When we talk about Federated Remotes, we also need to understand there are various ways you can fetch and load these modules into your host. Ill talk about just the main two strategies:</p><ul><li><strong>Eager:</strong> Load all remotes up front inside the host’s configuration. Must have knowledge of all remotes at startup. Must re-deploy Host when a Remote is updated.</li><li><strong>Dynamic:</strong> Load a single remote using React.Lazy on demand only when requested. Must have knowledge of only the requested remote when you view that page or component. Can update Remotes without redeploying Host.</li></ul><h3>Why is this so important?</h3><p>Abstraction and extensibility are constantly driving existing patterns to evolve to solve existing problems and create new patterns to aid in development experience, independent deployment, iterative development, long-term maintainability.</p><p>These focuses have become more and more of a problem as teams and applications grow in size. How do we get 50 engineers all working on a web application, owning their screens/components… while having them all operate and deploy completely independently. Now lets give the web application 100 screens and introduce scale concerns.</p><p>This problem is actually increasingly easy to solve using Microfrontends, with various added complexities and steps… But you add Module Federation into the mix and it all becomes so obviously simple.</p><h3>What could a Solution Architecture look like?</h3><p>Lets take a look at a simple example of a vanilla MFA Architecture.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/850/1*mu5fY2KTAIzKgG5ojfetrg.png" /></figure><p>In this example we are going to have an application with three pages. All three pages will use the same layout (header and footer) and will use react router to navigate between pages.</p><p><strong>Directories:</strong></p><ul><li><strong>Host: </strong>This is where the primary application lives, it is responsible for fetching remotes and configuration. Hosts can also potentially be responsible for adding layout, authentication, routing, and a unified experience.</li><li><strong>Remotes:</strong> These are our single page applications, collections of components, or feature based remotes.</li><li><strong>Shared:</strong> This is a build time dependency allowing non-packaged shared code that all remotes and the host can access.</li><li><strong>Service (Optional): </strong>This can be a simple BFF pattern that you can offload Host responsibilities into, such as Remote Orchestration and Configuration.</li></ul><h3>Lets walk through the Deployment!</h3><p>In this example we are going to have an application with five pages. All five pages will use the same layout (header and footer) and will use react router to navigate between pages.</p><p>The hosts and remotes are all built and deployed independently where a small difference is: <strong>Remotes are deployed to storage, and Hosts are deployed for Hosting.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZBB8RcZUJRoFn98U4_JIvQ.png" /></figure><h3>Responsible Autonomous Teams.</h3><p>So in real world practice, we want to ensure our teams have total control over their code-base having a say in how its built. This is always a noble goal but how to you ensure the teams don’t go off and build completely incompatible modules because somebody said “well I don’t like webpack.”</p><p>Well, in order for these pieces to be compatible, we need to ensure they are using the same framework and export types right? This is in direct conflict with the statement above. So what do we do?</p><blockquote>Well, its about being Autonomous in a responsible way.</blockquote><p>We build a solution architecture around Module Federation and say, you can build whatever, however within the confines of this framework. Initial reaction to this statement might be pretty jarring, or downright disagreement, but is that not the exact strategy of opinionated frameworks such as Angular?</p><p>One can be Autonomous in an Opinionated architecture, because they are free to focus their creativity and innovation in their product, or even making the opinionated framework better! But the important part is that innovation is shared with the rest of the organization so that we all grow and better each other, together.</p><h3>Hot Take: Monorepo or Polyrepo?</h3><p>So this is where folks tend to go off the rails. You can obviously go either way here, but you must understand the pros and cons before making this decision.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/498/1*RRe9t7TFeu-Z82ZaHik_-g.gif" /></figure><p>Thankfully I have an article where I outline the differences, the benefits, and ultimately my recommendation.</p><blockquote><a href="https://medium.com/@cfryerdev/monorepo-vs-polyrepo-the-great-debate-7b71068e005c">Monorepo vs Polyrepo: The great debate.</a></blockquote><p>If you would like to get to my preference without digging into the meat of another article, here it is;</p><blockquote>Personally, i feel its important to start with a mono-repo and graduate to a poly-repo when you absolutely need the flexibility of distributed code as the pattern proposed allows independent deployments of remotes. For me, its really that simple.<br><strong>~ Chris Fryer</strong></blockquote><h3>How does this benefit developers or an organization?</h3><p>Webpack module federation is a technique that allows you to share code between applications at runtime without requiring a build step. It allows multiple applications to work together as a single, integrated system, while still being developed and deployed independently. This can be particularly beneficial for organizations with autonomous teams and independent deployments.</p><p>Here are some benefits of webpack module federation:</p><ol><li>Improved developer productivity: Developers can work on their individual applications without worrying about how they will interact with other applications. They can focus on writing code for their application without having to think about the broader system architecture.</li><li>Faster time-to-market: With module federation, teams can release their applications independently and still have them work together as a single system. This can speed up the time-to-market for new features and products.</li><li>More flexible architecture: Module federation allows for a more flexible architecture where applications can be composed and re-composed dynamically at runtime. This can enable organizations to adapt more quickly to changing business needs.</li><li>Reduced duplication of code: With module federation, teams can share code between applications, reducing the need to duplicate code across multiple applications. This can lead to a more efficient use of developer resources and reduced maintenance costs.</li><li>Improved scalability: Module federation can help improve scalability by allowing applications to share resources dynamically. This can enable organizations to scale up or down based on demand without having to worry about resource constraints.</li></ol><p>Overall, webpack module federation can benefit organizations by enabling more efficient and flexible development and deployment practices, which can lead to faster time-to-market, improved scalability, and reduced maintenance costs.</p><h3>Bundlers, I can pick my own right?</h3><p>Currently at the time of this writing we have a few options with a few limitations; Web pack is obviously the most feature rich, but we also have RSpack and Vite. Vite does support module federation, but only eager loading as it does not have a browser runtime.</p><p>RSpack is currently in development with the immediate goal of full support of module federation with both eager and dynamic remote support.</p><p>In the coming months, module federation will supply a browser runtime that will enable Vite, RSpack, and other bundlers, to support dynamic remotes, but this may take some time to roll out to the general public.</p><p>I would expect to see many bundlers, supported in module federation by the first of the year, but we will see how that timeline shakes out.</p><h3>So its like perfect, right?</h3><p>Well, not really. There are still a lot of operationally important problems to solve such as:</p><ul><li>Style mutation and bundling</li><li>Code Sharing (in-directory vs npm-package)</li><li>Workspace solutions</li><li>Pipeline triggers</li><li>Remote Versioning</li></ul><h3>In Conclusion…</h3><p>If you are interested in creating a frontend development experience that scales with the size of your organization while still allowing you to deploy independently, this is where you need to be in 2022. Its not a perfect pattern, which I don’t believe one exists, but this framework provides the most flexibility of anything I have seen yet.</p><p>I do fully believe that this will be the standard organizations use to create modern experiences at scale in the very near future.</p><h3>Key Players I Recommend Following</h3><ul><li>Zach Jackson: <a href="https://twitter.com/ScriptedAlchemy">https://twitter.com/ScriptedAlchemy</a></li><li>Russell Canfield: <a href="https://x.com/RussellCanfield">https://x.com/RussellCanfield</a></li></ul><h3>Source Code:</h3><p><a href="https://github.com/cfryerdev/microfrontends-react-js-typescript">https://github.com/cfryerdev/microfrontends-react-js-typescript</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a411a289e670" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Docker to Podman]]></title>
            <link>https://medium.com/@cfryerdev/docker-to-podman-994cef4d0669?source=rss-ef7825d5c6e0------2</link>
            <guid isPermaLink="false">https://medium.com/p/994cef4d0669</guid>
            <category><![CDATA[podman]]></category>
            <category><![CDATA[docker]]></category>
            <dc:creator><![CDATA[Chris Fryer]]></dc:creator>
            <pubDate>Wed, 26 Jun 2024 15:32:05 GMT</pubDate>
            <atom:updated>2024-06-26T16:19:44.631Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*GMdjKMAJQ7IjBxKl" /><figcaption>Photo by <a href="https://unsplash.com/@acton_crawford?utm_source=medium&amp;utm_medium=referral">Acton Crawford</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>The landscape of container technology has been undergoing a significant transformation, particularly with Docker’s recent changes to its licensing model for enterprise users. This shift has prompted many organizations to reevaluate their container management solutions, driving a substantial migration towards Podman (Pod Manager).</p><p>This happened to me recently and a lot of my underlining tooling uses Docker under the hood. I don’t want to rewrite my tooling or wait for updates, so I want to install Podman, and use a docker alias so all my existing tools “just work”.</p><h3>Embrace Podman, for reals</h3><p><em>Skip this section if you dont care about why Podman is better than Docker. Its cool.</em></p><p>Podman encapsulates containers in a way that is both seamless and compatible with Docker, while also addressing some of the key challenges and limitations faced by Docker users. It’s designed to offer an easier transition for those accustomed to Docker, thanks to its similar command line interface and support for Dockerfile standards.</p><ul><li>Changes in Docker Licensing: With Docker altering its licensing model, enterprises are looking for cost-effective, open-source alternatives that don’t compromise on functionality or security.</li><li>Daemonless Architecture: Unlike Docker, Podman doesn’t depend on a central daemon, which enhances its security profile and reduces potential attack surfaces.</li><li>Rootless Operations: Podman’s support for running containers without root privileges addresses major security concerns, making it a favorite amongst system administrators and DevOps professionals.</li><li>Seamless Docker Compatibility: Podman supports Docker’s commands and Dockerfiles, making the transition less daunting for teams accustomed to Docker’s ecosystem.</li></ul><h3>Installing Podman</h3><h4>Windows &amp; Macos</h4><p>For those using non-Linux platforms, Podman Desktop offers a unified experience, bridging the gap with a user-friendly graphical interface for managing containers. It simplifies container development and deployment across platforms, ensuring that transitioning from Docker Desktop is as smooth as possible. Use this method, it installs Podman Desktop and it will also setup Docker Compose and Kubernetes support if you need it.</p><h4>Linux</h4><p>Podman is native to Linux and supports a variety of distributions. Here’s how you can install it on some of the most popular ones:</p><pre># Add Podman&#39;s repository<br>sudo sh -c &quot;echo &#39;deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_$(lsb_release -rs)/ /&#39; &gt; /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list&quot;<br><br># Download the GPG key<br>wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/xUbuntu_$(lsb_release -rs)/Release.key -O Release.key<br><br># Add the GPG key<br>sudo apt-key add - &lt; Release.key<br>sudo apt-get update -qq<br><br># Install Podman<br>sudo apt-get -qq -y install podman</pre><p>Note: You will need to setup Podman Desktop yourself here too.</p><h3>Setting up a terminal Alias</h3><p>To further ease the transition, you can alias Docker commands to Podman in your shell profile. This allows you to continue using familiar Docker commands, which Podman will interpret and execute.</p><h4>MacOS / *Nix</h4><ol><li>Open your terminal.</li><li>Add the alias to your .zshrc or .bash_profile file:</li></ol><pre>echo &quot;alias docker=&#39;podman&#39;&quot; &gt;&gt; ~/.zshrc<br>source ~/.zshrc</pre><h4>Windows</h4><ol><li>Open PowerShell.</li><li>Create a new alias:</li></ol><pre>Set-Alias -Name docker -Value podman</pre><h3>Update: SSL And Certificate Errors</h3><p>Where I work, I need a company zscaler cert to access https resources such as dockerhub so that I can actually pull down container images. I get SSL errors and it just fails. Here is an example error:</p><pre>Trying to pull docker.io/library/keydb:latest...<br>Error: initializing source docker://keydb:latest: pinging container registry <br>registry-1.docker.io: <br>Get &quot;https://registry-1.docker.io/v2/&quot;: tls: failed to verify certificate: <br>x509: certificate signed by unknown authority</pre><p>You have two main options to move past this, use a tls ignore flag or install the certificate to Podman:</p><h4>Use the Flag</h4><p>Podman has a flag you can include to ignore ssl errors called tls-verify which is used like so:</p><pre>podman run -d --tls-verify=false postgres</pre><h4>Install the Cert:</h4><p>Podman supplies some good documentation for this that I wont bother duplicating here: <a href="https://github.com/containers/podman/blob/main/docs/tutorials/podman-install-certificate-authority.md">https://github.com/containers/podman/blob/main/docs/tutorials/podman-install-certificate-authority.md</a></p><h3>Update: Podman 5.1 and ARM Compatibility</h3><p>Podman’s continued evolution brings an exciting development with the release of Podman 5.1, particularly for developers working on ARM-based systems, such as the Apple M series CPUs found in the latest Mac computers. This version introduces ARM compatibility, a significant enhancement that allows running x86 containers on ARM architectures seamlessly. Docker has had this feature for a while, and it worked great.</p><h3>Why is this Important?</h3><p>This development is a game-changer for developers and teams working across a variety of hardware ecosystems. It essentially resolves compatibility issues that were previously a challenge when moving containerized applications between x86 (common in desktops and servers) and ARM-based systems (increasingly popular in laptops and edge devices due to their efficiency).</p><p>Running x86 containers on ARM with Podman 5.1 doesn’t require any additional configuration. Podman automatically detects the architecture mismatch and uses QEMU to run the containers. However, you should note that while this feature greatly enhances flexibility, performance might not be on par with running containers natively due to the overhead introduced by emulation.</p><p>To take advantage of this feature, ensure you have Podman 5.1 or later installed on your ARM-based system. If you’re using an older version of Podman, refer to the installation instructions provided earlier in this article to upgrade to the latest version.</p><h3>Conclusion</h3><p>Transitioning from Docker to Podman should help you use the same tooling and commands you know and love, without the added Docker license headache.</p><p>The introduction of ARM compatibility in Podman 5.1 marks a significant milestone for containerization technology, offering broader flexibility and supporting a more inclusive range of computing environments.</p><p>Stay tuned to the Podman release notes and documentation to keep abreast of new features and improvements, ensuring you’re leveraging the most out of your container management tool.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=994cef4d0669" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Monorepo vs Polyrepo: The great debate.]]></title>
            <link>https://medium.com/@cfryerdev/monorepo-vs-polyrepo-the-great-debate-7b71068e005c?source=rss-ef7825d5c6e0------2</link>
            <guid isPermaLink="false">https://medium.com/p/7b71068e005c</guid>
            <category><![CDATA[monorepo]]></category>
            <category><![CDATA[repositories]]></category>
            <category><![CDATA[polyrepo]]></category>
            <dc:creator><![CDATA[Chris Fryer]]></dc:creator>
            <pubDate>Fri, 28 Apr 2023 21:21:16 GMT</pubDate>
            <atom:updated>2023-05-10T00:14:42.549Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*g2gcQ7oVMKH5faMihfdVeA.jpeg" /><figcaption>Photo by trybaarchitects.com</figcaption></figure><p><em>Note: The contents of this article are my opinions, not the views or opinions of my employer or other entity. Please feel free to give it a clap, it helps!</em></p><h3>Introduction</h3><p>In my travels as an engineer and consultant, one topic comes up repeatedly that has created some spirited and passionate discussions. Alright, lots of arguments and opinions. It is an important part of application development at scale or at the enterprise level so we should really understand our options before making an emotionally based decision.</p><p>Before we get too deep into it… lets understand our two main options:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/1*aPcGEHIbYlL_lj2KqQodqQ.gif" /><figcaption>RIP</figcaption></figure><h3>Mono-Repositories</h3><p>Monorepos, or repositories that contain multiple projects, have become increasingly popular in recent years. There are several benefits to using a Monorepo for your projects.</p><p>First, a Monorepo allows for easier sharing of code and resources between projects. This can save time and reduce code duplication, as developers can easily reference and reuse existing code. Additionally, a Monorepo can make it easier to manage dependencies and versioning, as everything is located in one central location.</p><p>Another advantage of a Monorepo is that it can help to improve collaboration between teams. With all projects housed in one repository, it is easier for different teams to work together and share their work. This can lead to improved communication and collaboration, as developers can easily see what others are working on and make suggestions or provide feedback. In addition, it can help to ensure consistency across projects, as all code is located in one place and can be easily reviewed and approved.</p><p>However, there are also some potential drawbacks to using a Monorepo. One potential issue is that a Monorepo can become quite large and complex over time, which can make it difficult to manage and maintain. Additionally, it can be challenging to ensure that all code changes are properly tested and reviewed, as there may be many projects and teams working in the same repository. Finally, some developers may prefer to work on smaller, more focused projects, rather than having to navigate a large Monorepo.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/1*7Od_QWnvnkkrewSydErxGQ.gif" /><figcaption>We all make decisions together, we all grow together.</figcaption></figure><h4>Summary of Monorepos</h4><ul><li>Easier sharing of code and resources between projects</li><li>Reduced code duplication and improved code consistency</li><li>Easier management of dependencies and versioning</li><li>Improved collaboration between teams</li><li>Better communication and knowledge sharing</li><li>Increased visibility into what other teams are working on</li><li>Monorepos can become large and complex over time</li><li>Difficult to ensure all code changes are properly tested and reviewed</li><li>Some developers may prefer to work on smaller, more focused projects</li><li>Higher risk of merge conflicts and build failures</li><li>Longer build times due to larger codebase, without proper pipeline targets</li><li>May require more discipline and organization to manage effectively</li></ul><h3>Poly-repositories</h3><p>Polyrepos, or repositories that contain a single project, have their own advantages and disadvantages compared to Monorepo. One of the primary benefits of a Polyrepo is that it promotes independence and autonomy for each project. Developers can work on smaller, more focused projects, which can be more manageable and easier to navigate. Each repository can have it’s own build and deployment processes, allowing for greater flexibility.</p><p>Another advantage of a Polyrepo is that it can make it easier to enforce code quality and review processes within individual repositories. Each project is independent and has it’s own repository, which can make it easier to manage and maintain. This can lead to improved code quality and consistency within individual projects.</p><p>However, there are also potential drawbacks to using a Polyrepo. One potential issue is that it can be more difficult to share code and resources between projects, which can lead to duplication and inconsistency. Additionally, communication and collaboration between teams can be more challenging, as they are working in separate repositories. Managing dependencies and versioning can also be more complex, as each repository may have it’s own dependencies and versioning requirements. Ultimately, the decision to use a polyrepo or a Monorepo will depend on the specific needs and goals of your organization.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/1*f1eanKhKj96uXC08ETjTmw.gif" /><figcaption>Sometimes, it’s best we move and innovate as separately governed bodies.</figcaption></figure><h4>Summary of Poly Repositories</h4><ul><li>Each project is independent and has it’s own repository, making it easier to manage and maintain</li><li>Developers can work on smaller, more focused projects, which can be more manageable and easier to navigate</li><li>Each repository can have it’s own build and deployment processes, allowing for greater flexibility</li><li>Lower risk of merge conflicts and build failures due to the smaller codebase</li><li>Easier to enforce code quality and review processes within individual repositories</li><li>More difficult to share code and resources between projects, which can lead to duplication and inconsistency</li><li>Increased overhead in managing multiple repositories, including managing dependencies and versioning</li><li>Communication and collaboration between teams can be more challenging, as they are working in separate repositories</li><li>Greater risk of inconsistencies and versioning issues across repositories</li><li>Can be harder to ensure consistency and enforce standards across all projects</li></ul><h3>Making your decision</h3><p>When making your decision, you should factor in two important concepts. Team Maturity and the Importance of Collaboration.</p><ul><li><strong>Team Maturity:</strong> Monorepos are often a better fit for mature and experienced teams who can handle the complexity of managing a large codebase. These teams may have established communication and collaboration processes in place, as well as robust testing and review processes to ensure code quality. On the other hand, Polyrepo may be a better fit for newer teams or teams with less experience, as they can help to promote independence and autonomy for each project. These teams may benefit from the simpler structure of a Polyrepo, which can make it easier to manage individual projects and enforce code quality standards.</li><li><strong>Collaboration Importance:</strong> Monorepos are often a better fit when collaboration and code sharing are important, as they provide a central location for all code and resources. This can make it easier for developers to share ideas and collaborate on projects, leading to improved communication and collaboration. Additionally, with all code in one place, it’s easier to ensure consistency and enforce standards across all projects. On the other hand, Polyrepo may be a better fit for projects where collaboration and code sharing are less important, as they allow for greater independence and autonomy for each project.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/1*5Gs3ugpCGP8Z0J-_yN5Sng.gif" /><figcaption>Its a tough decision, and not everyone will be happy about it.</figcaption></figure><h3>My Recommendation</h3><p>Personally, I feel it is important to start with a Monorepo and graduate to a Polyrepo when you absolutely need the flexibility of distributed code as the pattern proposed allows independent deployments of remotes. For me, it is really that simple.</p><p>If you have teams who are strong but do not collaborate, actively refuse, or do not share solutions… a Monorepo may be a good choice to create that environment and create a “we all win together, we all lose together” situation. It can also level up some of your more junior engineers, who may not have exposure to projects that more senior folks work in.</p><p>Both options are viable solutions that solve different problems in different ways. You can easily create a mess in any technology or pattern. So with that in mind, lets crank out some code!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/1*QZ5iVNt-hy6yhRSx28sYaQ.gif" /></figure><h3>In conclusion</h3><p>But remember, There is no one-size-fits-all solution and it really has to be decided as a team based on whats important to your company culture and organizational objectives. Have the conversation, keep an open mind, be respectful, and also understand that most seasoned engineers have had positive and negative experiences in both patterns.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/498/1*z7Dvp4EimmfDKtkjFO2F0w.gif" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7b71068e005c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Cluster Scaling, Simply.]]></title>
            <link>https://medium.com/@cfryerdev/cluster-scaling-simply-aeb0bf763f4b?source=rss-ef7825d5c6e0------2</link>
            <guid isPermaLink="false">https://medium.com/p/aeb0bf763f4b</guid>
            <category><![CDATA[cluster]]></category>
            <category><![CDATA[clustering]]></category>
            <category><![CDATA[services]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[scaling]]></category>
            <dc:creator><![CDATA[Chris Fryer]]></dc:creator>
            <pubDate>Tue, 13 Oct 2020 01:14:17 GMT</pubDate>
            <atom:updated>2020-10-13T14:52:54.051Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*pjUXFm6_eVXRtDsL" /><figcaption>Photo by <a href="https://unsplash.com/@therealcaique?utm_source=medium&amp;utm_medium=referral">Caique Morais</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><blockquote>Note: The contents of this article are my opinions, not the views or opinions of my employer or other entity.</blockquote><blockquote>Note: This article is a self-made challenge to myself, to write an article, diagram, review, edit, and publish it within three hours, and be OK with the outcome. Putting yourself out there on the internet can be stressful, but its a wonderful experience.</blockquote><p>When determining how to scale a service cluster, you have two main knobs to turn: Scaling up or Scaling out. It is important to understand how and when to use each to avoid over provisioning in your cluster and incurring surprise costs and traffic latency.</p><p>It is critical to understand how the services in your cluster will behave and what type of traffic they will see on a regular basis. But sometimes, in greenfield development, you won’t know until the traffic is live, so we have to prepare for that as well.</p><p>Without proper scaling strategies, your cluster can grow out of control!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/400/1*NIymTvmPi1SURqLsqCwQ-g.gif" /><figcaption>Don’t just get the biggest instance possible.</figcaption></figure><h3>Scaling Directions</h3><ul><li><strong>Scaling Up/Down:<em> </em></strong><em>Increasing or decreasing the resources (processors or memory) of a instance. This requires a new instance to be provisioned and the new scale becomes available, and requires no outage.</em></li><li><strong>Scaling In/Out: </strong><em>Increasing or decreasing the count of instances in your cluster. This requires a new instance to be provisioned and the new scale becomes available, and requires no outage.</em></li></ul><h3>Workload Traits</h3><p>There are several types of workload traits commonly seen in clusters, a few to be aware of are:</p><ul><li><strong>Traffic Volume:</strong><em> (How many requests) The most common workload is traffic volume. When more and more clients are hitting a service in your cluster, the traffic will drive up CPU, and maybe even Memory usage, in a linear manner.</em></li><li><strong>Transaction Time:<em> </em></strong><em>(How long a request takes) In rare cases, you will see long running transactions. This could be something as simple as a bulk task that is used to process data each night. This type of workload may drive up CPU and Memory usage, for a period of time, in a flat manner.</em></li><li><strong>Transaction Size:</strong><em> (How much the request has to do) You may also see larger transactions when a resource is requested. This can be anything from scheduled background processing or an expensive set of calculations from multiple systems. This type of workload may drive up CPU and Memory usage, for a period of short time, in a spiked manner. This can also cause issues in relation to traffic volume and transaction time which may be harder to spot.</em></li></ul><p>Below, we will be going through an example cluster, provide some scenarios, and see how the cluster could react in the real world.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/260/1*uct2KnJFQImg26gn_l68sw.gif" /><figcaption>Hopefully, it wont react like this.</figcaption></figure><h3>Our Simple Cluster</h3><p>In this example, we have a cluster which contains an instance with 2 cores and 2gb of ram. With normal traffic, this instance has about 35% of the resources in use, and the scale point set to 70%. The overall goal is to find the perfect balance between scale peaks and valleys, while being strategic around how we will scale the cluster for the unforeseen.</p><p><em>Note: When you have more than one instance in a cluster, you can divert traffic either equally across instances (Balanced) or at a scale point. For this example, we will just use the scale point.</em></p><p>Lets go through an example scenario and see how the cluster reacts and why…</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/712/1*amhEb-EqzlTjg87Jp_EcIw.png" /></figure><p>Here we are, default state, everything is running smoothly, and traffic is behaving as expected. My only note here is, are you are probably spending slightly too much on the instance size; You <em>could </em>scale down here.</p><p>But wait, we just had 10x the users hit our service all at once, and we didn’t anticipate the need to scale out! We now have a completely maxed out instance and requests to the server are timing out…</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/381/1*vrHEipmwmQeEIfR9gaxCUA.gif" /><figcaption>As it does…</figcaption></figure><p>Lets scale out to two instances, quickly!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/713/1*MaJGyzXHHiYm22yqxRerUQ.png" /></figure><p>Alright, we scaled out to two instances of the same size, so we have traffic waiting for the other instance to spin up before we load balance traffic. <em>This can take a couple minutes.</em> Lets see what happens to the cluster once that instance is live…</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/723/1*bPcrq31FrKbgFoTO7umdNw.png" /></figure><p>Interesting, the traffic died down a little, but is hovering right above our scale point. Oops, we have accidentally introduced a new problem… We are now paying for two instances but really only using the resources of about than one. We have three options: scale up, wait it out, or raise the scale point.</p><p>Sometimes, incurring this additional cost is acceptable, and the right solution is to simply wait out the traffic spike, and learn from it. Sometimes its expected and accepted that we have two instances always available, because we know these services will see regular spikes above the 70% mark.</p><p>Scaling-Up will solve the problem and raise the scale point as it’s merely a percentage of the total resources, but will also incur more monthly costs each month.</p><p>Raising the scale point will solve the problem in the short term, and not incur any new monthly costs, but may only put off the problem you had should you start to see moderate traffic regularly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/724/1*v8meXPt07JCDM_mOoLG0ZA.png" /><figcaption>Here, we kept the two instances, scaled them down, and balanced traffic evenly across them.</figcaption></figure><p>Really to fully solve this, you have to find a good balance that incurs costs only in extreme cases, does not regularly overly spend on non-utilized resources by running too many instances, while provisioning only the smallest instance size needed.</p><p>This is an art.</p><h3>Can’t we scale automatically?</h3><p>Well, yes. This is called auto-scaling, and is built in to most cluster solutions, but for this example its easier to pretend that doesn’t happen so we can talk through the pros and cons of each strategy.</p><h3>Break it apart…</h3><p>Something you should always ask yourself as you start to see trends in traffic: <strong><em>Should this service be broken up, so different parts of the logic can be scaled differently?</em></strong> This is easily the most important question you should be asking yourself as you see new data from your cluster logs.</p><p>If your service sees varying types of traffic and workloads, break it up and make each service smaller. This will also dramatically change your scaling strategy. Eventually over time, each service will get broken up into small, independently deploy-able, services that serve a simple purpose.</p><p>This is the natural evolution of services and clusters. Embrace it!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/498/1*91ms9YXw2EUcLY7BNg0pcQ.gif" /><figcaption>Each service should be small, tiny, compact!</figcaption></figure><p>Speaking of small…</p><h3>Strive for the smallest</h3><p>When building out your service, or your cluster, you should strive for the smallest footprint possible. Here are some more questions to ask yourself throughout the development and deployment process:</p><ol><li>Whats the minimum number of CPU cores the service needs to handle the average daily workload?</li><li>What’s the minimum amount of memory to sustain the service?</li><li>Can the service be refactored to maintain memory better?</li><li>What is the minimum number of instances needed to handle the traffic?</li></ol><h3>Conclusion</h3><p>Understanding how clusters behave based on traffic, workloads, and resource usage is paramount to creating a cost effective and performant solution. Even if we do not know how the cluster will be used or what type of traffic we will see, you can be proactive and use the experience to become a master at tuning clusters.</p><p>It can be extremely fun and rewarding to crack this nut, and I hope I have inspired you to dive in with both feet and enjoy yourself. As I said, this is an art, be a cluster artist.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/444/1*ve-h9Xcvl89f6iiDTG-l7Q.gif" /><figcaption>Hey, I just really like the office.</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=aeb0bf763f4b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Iterative Monolith to Micro-services, in ~10 minutes.]]></title>
            <link>https://medium.com/@cfryerdev/iterative-monolith-to-micro-services-in-10-minutes-9aa33997ce45?source=rss-ef7825d5c6e0------2</link>
            <guid isPermaLink="false">https://medium.com/p/9aa33997ce45</guid>
            <category><![CDATA[microservices]]></category>
            <dc:creator><![CDATA[Chris Fryer]]></dc:creator>
            <pubDate>Tue, 15 Oct 2019 16:24:23 GMT</pubDate>
            <atom:updated>2019-10-15T16:24:23.214Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*7zZZSzDH48Plo8k9" /><figcaption>Photo by <a href="https://unsplash.com/@planner1963?utm_source=medium&amp;utm_medium=referral">Pieter van de Sande</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p><em>Before we begin, if you need a bit of a refresher on Micro-services, I wrote an article that should get you up to speed: </em><a href="https://t.co/gurxwHqXFN"><em>Micro-service Architecture and Design</em></a></p><h3>What are we trying to accomplish?</h3><p>So, you were asked to break down a monolith into micro-services while keeping the monolith alive. <strong>Yikes</strong>. You also learned the business plans on adding features to the product while you are breaking it apart! <strong>Double Yikes</strong>. Oh, and one more thing, do not touch the front end…</p><p>For many of us, it can feel like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/455/1*nFE1twKCcL9n8FZ7V75r9w.gif" /></figure><h3>Ugh, how do we break it down?</h3><p>In many cases, “<em>just rewrite it</em>” will just not work for the business and you may need to break down a monolith iteratively while supporting existing development. This can be a really tricky process, and includes a ton of risk if you attempt it without a plan. When putting your plan together, break down everything the monolith does and group them in self contained modules. These modules may also include items the product needs to do in the future.</p><blockquote><strong>Module: </strong>A functional chunk of an application that services a single or small subset of features.</blockquote><p>Defining the list of modules that encapsulate all the functionality of the monolith is extremely important, as the business will need to make some tough decisions around feature freezes, priorities, timelines, and more:</p><ul><li><strong>Timelines:</strong> When you define your modules, take some time and T-Shirt size the modules relative to each other. This will give you a VERY high-level estimate of how much total work is required to replace the monolith. Don’t worry if its not super accurate, its a swag, but weekly updates from each team will help leadership understand where they are in the process.</li><li><strong>Pay Twice vs Waiting: </strong>You can’t ask the business to suspend all feature development on the product, but if they want some new feature, you could tell them to wait and have it built in the new system, or build it in the monolith, and then again in the new micro-services. Twice the cost.</li><li><strong>Dependencies: </strong>You should look at all the modules and their inter-dependencies and clearly communicate/document them. This determines the technical order they should be rebuilt in.</li><li><strong>Feature Freeze:</strong> When a module is being rebuilt, I recommend a monolith feature freeze on this functionality while the micro-service is being built to replace it. This serves two purposes: 1) <em>Protect from feature drift, don’t chase a moving target, you will never catch it.</em> 2) <em>Allows you to take your time and understand WHY the module does what it does.</em></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*hQgVkMUJW9OBEBDqqQ-Axw.gif" /><figcaption>How it feels when you start …</figcaption></figure><h3>Alright, got it, what’s the plan?</h3><p>If we look at the example below, we have three main states that have to take place when iteratively breaking a monolith down:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2XF_l_2aWo5-KFBD0BjZIA.png" /><figcaption>The three generic states of monolith to micro-service deprecation.</figcaption></figure><ul><li><strong>Current State:</strong> You’re currently on the monolith, it’s big and slow and sometimes you cry in the shower. (possibly unrelated)</li><li><strong>Middle State:</strong> You support both platforms in this state, where you may or may not have refactored the frontend. Depending on where you are in the frontend, you may talk to the micro-services or you may still need to talk to the monolith. Not ideal, but the gateway handles all of the mixed routing for you. For the databases, we ETL data from the existing database to a new optimized structure.</li><li><strong>End State:</strong> You’re off of the monolith, yay. Feel free to print the monolith’s source code and literally burn it. Enjoy it, you’ve earned it.</li></ul><p>Typically, we move from left to right in this example chronologically, and 90% of the time, we are in the Middle State. We will repeat the Middle State for each module we are rebuilding.</p><p>To keep from having to update code in the frontend, or rewrite it, we create a Gateway between the frontend and all of our services. All this serves is a way to hold on to http routes, and send the request to the correct service. This makes it easier to move services around without touching your frontend.</p><p>During the Middle State, the gateway will have legacy routes to support the frontend functionality that still needs to talk to the monolith, while also storing optimized routes for talking to the new micro-services. Some folks like to create two gateways to keep the new optimized gateway clean. Personally, I like that.</p><p><strong><em>Note:</em></strong><em> I plan on writing an in depth article on Middle State.</em></p><h3>What if I am allowed to replace the frontend too?</h3><p>In the interest in making the problem harder, I opted out of replacing the frontend on top of a monolith. This makes things more straight forward to explain, but what if you are actually allowed to replace that?</p><p>Well, simply put, it’s really all about the gateway in the example earlier in the article. If you opted for two gateways, your new frontend should talk to the optimized gateway. If you have one gateway with mixed routes, simply put, both frontends will talk to the same gateway.</p><h3>OK, what exactly do we do in the Middle State?</h3><p>Typically we have many teams running in parallel during the Middle State, each team managing the development of a single module. That team should have a backlog, roadmap specific to that module, and a release plan. Each team should be responsible for weekly status updates to the business so they can track the total progress of the project at a high level.</p><p>Cross team dependencies and blockers should be communicated often and escalated up if it effects the sprint, roadmap, or another teams ability to deliver. The business will understand!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/386/1*PXiaEBvJqCqkYPShjKQA9w.gif" /></figure><p>Things like this <strong>will</strong> happen, and communication is key. As long as the business can plan around issues and still feel in control, they will understand. They are there to make the tough decisions, and you are there to give them the data to make those decisions.</p><h3>How about the database? ETL?</h3><p>Often times, the monolith’s database is just as crufty as the code base, so we should probably think about refactoring that as well. We will want to identify which tables support which module in our monolith and migrate what’s needed from each.</p><p>One pattern in micro-services is to have a single database per micro-service. This very often complicates the migration process, so to handle this, we introduce a process called Extract Transform Load. (ETL) In this process, we identify which fields/tables are required with the new micro-services and what is the optimum data structure. Might as well clean it up while we are here!</p><p>Once the database and required data/structure are in place, you should be free to route traffic to your new micro-service via the gateway. This database is now the source of truth. Off to the races!</p><h3>Conclusion</h3><p>When you break down the plan, it’s actually quite simple and easy to follow. As long as you have weekly updates to stakeholders, hold the business accountable for decisions, and communicate blockers, it should go pretty well for everyone!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/300/1*1A1EpeeQ0xEOfLga8dGqzQ.gif" /><figcaption>I love the office.</figcaption></figure><p>Go get em.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9aa33997ce45" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Microservice Architecture & Design]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@cfryerdev/microservice-architecture-design-2ac7eaae532?source=rss-ef7825d5c6e0------2"><img src="https://cdn-images-1.medium.com/max/2600/0*bato6iN0c0bkF2jT." width="5184"></a></p><p class="medium-feed-snippet">Note: The contents of this article are my opinions, not the views or opinions of my employer or other entity.</p><p class="medium-feed-link"><a href="https://medium.com/@cfryerdev/microservice-architecture-design-2ac7eaae532?source=rss-ef7825d5c6e0------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://medium.com/@cfryerdev/microservice-architecture-design-2ac7eaae532?source=rss-ef7825d5c6e0------2</link>
            <guid isPermaLink="false">https://medium.com/p/2ac7eaae532</guid>
            <category><![CDATA[microservices]]></category>
            <dc:creator><![CDATA[Chris Fryer]]></dc:creator>
            <pubDate>Fri, 30 Aug 2019 16:33:13 GMT</pubDate>
            <atom:updated>2019-08-30T16:33:13.308Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Dependency Injection — Composition Root]]></title>
            <link>https://medium.com/@cfryerdev/dependency-injection-composition-root-418a1bb19130?source=rss-ef7825d5c6e0------2</link>
            <guid isPermaLink="false">https://medium.com/p/418a1bb19130</guid>
            <category><![CDATA[composition-root]]></category>
            <category><![CDATA[autofac]]></category>
            <category><![CDATA[dependency-injection]]></category>
            <category><![CDATA[inversion-of-control]]></category>
            <dc:creator><![CDATA[Chris Fryer]]></dc:creator>
            <pubDate>Fri, 20 Apr 2018 16:13:25 GMT</pubDate>
            <atom:updated>2018-04-23T18:48:46.346Z</atom:updated>
            <content:encoded><![CDATA[<p><em>The Dependency Injection Pattern — Composition Root</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*v64bjNPwmjsMeya6." /><figcaption>Photo by <a href="https://unsplash.com/@apreble?utm_source=medium&amp;utm_medium=referral">Andrew Preble</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Part 1: <a href="https://medium.com/@cfryerdev/dependency-injection-general-54898b6f18f5">Dependency Injection — A general breakdown</a></p><p><em>Note: The contents of this article are my opinions, not the views or opinions of my employer or other entity.</em></p><h3><strong>The Composition Root Pattern</strong></h3><p>The composition root pattern is (in my opinion) the next evolutionary step after learning dependency injection. Once you fully understand dependency injection, you are able to introduce the next logical steps; predictability and structure around how dependencies are managed. Composition Root brings this to the front of the line, and gives engineers confidence around the structure of their application and how data flows. This is one of those patterns that give you the feeling “oh my god, why didn’t I think of this, why isn’t this how everything is structured?”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/247/1*Llke34Fdi5nEEgk83kfrYw.gif" /></figure><p>All dependencies are defined, constructed, and injected into the container as soon as possible in a process. This may slow down the init of your service by a few seconds, but it gains you one incredible positive: On request, the dependency chain is 100% pre-calculated and in some cases, pre-constructed. This keeps response times incredibly low and consumes very little memory. You also fail fast, in the sense that you will know before users are brought into the service, if something is not working correctly.</p><p>Depending on the container you chose, there are additional features that become available to you when you adopt this solution. One of these is circular dependency detection. This may be difficult to catch or debug when you simply keep a running list of registers in a cs file. Heck, a whole new level of unit testing becomes available to you which we will also cover below.</p><p><strong>Note:</strong> There is an example github project at the bottom.</p><p>Through the course of this post, keep one thing in mind:</p><blockquote>The API knows about the container, and nothing else. The container knows about everything else.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/440/0*1sl_F0v6tq1zQjJ9." /></figure><h3>Principals</h3><ul><li><strong>Single location for object construction: </strong><em>Entire dependency graph is discover-able in one location.You can reference installers from other assemblies.</em></li><li><strong>Assembly Scanning allows the container to discover your dependency graph for you:</strong> <em>Ensures all dependencies of a certain type are located and constructed identically.</em></li><li><strong>Build a Lean Container:</strong> <em>The composition project is a map of how your dependencies are constructed, how they interact, and how they are resolved. Do not register items in your container that may be optionally consumed. Avoid auto-wires if possible.</em></li><li><strong>As close to Init or Entry Point as possible: </strong><em>As soon as we have an active process, we want to construct the container. The only dependency construction allowed before Composition is logging.</em></li><li><strong>Pass configuration to the container for object construction: </strong><em>The container has all configuration necessary to build ALL dependencies.</em></li><li><strong>Predictable Dependency Graph:</strong><em> All calls to the project should have a pre-constructed, pre-discovered dependency chain. No dependencies are built on the fly.</em></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/361/1*XEvuVWuZz4_8qtJznc_cQA.png" /><figcaption>An example solution where an API uses a Composition project to construct the container, and leverages the Installers/Builders to register dependencies.</figcaption></figure><h3><strong>Things to avoid</strong></h3><ul><li><strong>Stick to constructor injection: </strong><em>Do not mix injection strategies. Where you cannot use constructor, use a Dependency Resolver.</em></li><li><strong>Avoid one-off registrations:</strong> <em>Register using an installer or builder. (depending on your container)</em></li><li><strong>Never register an item in your container outside of your Composition Root project.</strong> <em>Certainly not during units of work.</em></li></ul><h3>Lean Architecture</h3><p>A predictable dependency graph is incredibly important when you start building lean and scalable services. Just knowing how/when your dependencies are constructed and how their dependencies behave is crucial. A valuable piece of knowledge is having visibility into how newly added dependencies are co-mingling with pre-existing dependencies, and if they are not, failing fast if dependencies fail to resolve correctly or are registered incorrectly.</p><p>The biggest gain is upon request, a good portion of your dependency graph should be pre-constructed and ready for your consumption. Resolving is expensive, especially if you have a lot of components registered.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/425/0*JVbakdfkzqPmKBj1.png" /><figcaption>Artillery.io test showing an average 8ms response time against a .net core micro-service using the Composition Root pattern. This test hit a controller for 60 seconds, with 30 new virtual users arriving every second. <strong>Layers: </strong>Controller &lt;-&gt; Manager &lt;-&gt; Entity Framework &lt;-&gt; Sql Database</figcaption></figure><h3>Assembly Scanning</h3><p>A common practice in (DI) Composition Root is assembly scanning. This means reading the assemblies in your solution for concrete implementations that match a specific signature so the container can register them automatically. Example: Instead of registering all of your managers individually, you register all classes that implement IManager. Any engineer who creates a new manager, as long as they use the correct interface, the container will handle everything for them. No need to go add a registration for that class!</p><p>One common issue when using Assembly Scanning is fighting JIT. When a .net process is running, it does some clever stuff to save memory and optimize itself. One of those things is how JIT handles referenced assemblies. Only assemblies that have a physically referenced class will be loaded into memory. So if you reference another assembly in your project, unless you call something within it, it will not be present in memory for Assembly Scanning to find it. Below is an example of Assembly scanning which also takes into consideration the JIT issue.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/645/1*aW4o6X608du2mHtArWl9_g.png" /><figcaption><strong>Example</strong>: Here is an AutoFac example of assembly scanning to register items that inherit from the BaseService class.<em> I placed an Init class in the assembly and called it. This is done to ensure JIT has loaded the assembly in memory. This is a highly generic example to illustrate the issue, many containers such as AutoFac solve this by poking referenced assemblies for you if you use a function such as GetReferencedAssemblies();</em></figcaption></figure><h3>Unit Testing</h3><p>One of the benefits to the Composition Root pattern testing your code, the same way its implemented. A cost to mocking out methods, dependencies and objects is you may make a mistake in your mocking that allows the test to pass, without accurately testing the functionality. Having a single point of registration, as well as following the Installer/Builder pattern allows us to unit test our code with the same exact container in the same state as the application we are testing. This eliminates (for the most part) false passes due to poorly mocked tests.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/783/1*OQpbfYtaCdfAvMSDijWxqw.png" /><figcaption><strong>Example</strong>: We build a container for our tests and then attempt to resolve a controller.</figcaption></figure><p>You also have the freedom to replace registrations in your container, with mock versions. For example, instead of using my IDbContextFactory to resolve Entity Framework DB Contexts, I may want to replace it with one that always returns a Mock DBContext or one with the default provider to to InMemory.</p><p>Another aspect to unit testing that becomes available to you, is unit testing the dependency graph and/or the container itself. Imagine testing that the container is able to construct the entire graph, in the correct order, and resolves dependencies in an adequate amount of time.</p><h3>Controlling Configuration</h3><p>One of the coolest functions of this pattern is controlling how configuration is handled in your application. You can easily use it to standardize how configuration is handled, or who has access to it. Your container should have access to configuration to construct all the necessary dependencies and register them. The challenge, only include configuration in memory for a handful of milliseconds:</p><p>Once your configuration is handed to your container and the dependencies are constructed… Why not just dispose of your configuration in memory? Always protect any internal variables that contain keys, connection strings, or sensitive configuration. If you cannot protect the variable (you don’t have src access to the object), abstract it behind a factory.</p><p>There is no silver bullet, but this is a fun challenge I love to solve or watch others solve!</p><h3>Conclusion</h3><p>As I said earlier, the composition root pattern is (in my opinion) the next evolutionary step after learning dependency injection. It takes your understanding of Dependency Injection and builds on those principals without changing directions. This pattern should approachable to those who have a real interest in creating lean structures.</p><p>This pattern gives engineers an easy to adopt framework where things “just work” while also providing a depth at which they choose. If they want to learn how a dependency is constructed, how changing a dependency creates a ripple effect, or how two dependencies may work together; they can choose how deep they want to go.</p><p><strong>Here is an example project for you to explore on your own:</strong> <a href="https://github.com/cfryerdev/composition-root-example">GITHUB</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=418a1bb19130" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Dependency Injection — General]]></title>
            <link>https://medium.com/@cfryerdev/dependency-injection-general-54898b6f18f5?source=rss-ef7825d5c6e0------2</link>
            <guid isPermaLink="false">https://medium.com/p/54898b6f18f5</guid>
            <category><![CDATA[inversion-of-control]]></category>
            <category><![CDATA[dependency-injection]]></category>
            <dc:creator><![CDATA[Chris Fryer]]></dc:creator>
            <pubDate>Fri, 20 Apr 2018 15:02:17 GMT</pubDate>
            <atom:updated>2018-04-20T15:02:17.957Z</atom:updated>
            <content:encoded><![CDATA[<p><em>The Dependency Injection Pattern —A general breakdown</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*JWtAe5eFb_Zc0JWu." /><figcaption>Photo by <a href="https://unsplash.com/@owencavlys?utm_source=medium&amp;utm_medium=referral">Owen CL</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p><strong><em>Note: </em></strong><em>The contents of this article are my opinions, not the views or opinions of my employer or other entity. This article is a precursor for my Composition Root article.</em></p><h3>What is Dependency Injection?</h3><p>Dependency injection is a form of Inversion of Control which focuses around supplying dependencies to a class explicitly as opposed to constructing them, or requesting them. My favorite definition of Dependency Injection is as follows:</p><blockquote>Dependency Injection (DI) is a pattern that helps developers decouple different layers of an application. It provides a mechanism for the construction of dependency graphs independent of the class definitions.</blockquote><p>This pattern also allows an engineer to inspect a class constructor and determine the dependencies required to use or test the class. In a fully dependency injection application, all object construction should be handled by the container. The container will also manage nested dependencies which we call the Dependency Chain. The make-up of one of more dependency chain in an application is known as the Dependency Graph.</p><h3>Object Construction Methods</h3><p>There are many ways to skin a cat, but for this example I will break it down to <strong>three main solutions </strong>for object construction in the context of a .net application. For this example, we will keep it simple and consume a <em>UserDbContext</em> which has a (string) dependency of a connection string. We want to consume this class in a Manager and expose two operations from the <em>UserDBContext</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/787/0*_Qls5nvsi0hjpxlK." /><figcaption><strong>Example</strong>: This is a standard new() construction method. Here we have to supply the UserDbContext’s dependency when we construct it. Once we can construct it, we can use it. This has no form of IoC and simply uses the new keyword. This breaks down as you need to reuse the UserDbContext in multiple classes, you need to supply the connection string on each construction. Obviously this would be a bad pattern if the connection string needed to change based on the logged in user. This would also be a pain to maintain.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/789/0*pky7CqlyW6kvb3_I." /><figcaption><strong>Example</strong>: Here we will use the Service Locator pattern to resolve the UserDbContext and call the two operations. This is a little better than the new() method, but obscures things a little bit. With service locator, the instance would be created early in the startup of the application, but would always return that instance to anyone who asks for a UserDbContext. This pattern conceals the dependencies of the Manager class. Because of this, it also makes unit testing the manager quite difficult.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/782/0*aOyo_4vxl6EN3sDX." /><figcaption><strong>Example</strong>: Lastly, we will simply inject the context into the manager and use it. The container will be responsible for creating the UserDbContext and supply UserDbContext’s dependencies. With a DI COntainer, the instance would be created early in the startup of the application, and allows you to control whether everyone gets the same instance or a fresh instance. (Singleton/Transient) Another benefit is the developer does not need to care about what UserDbContext’s dependencies, but can if it goes to the class definition. It also allows an engineer to look at the constructor of a manger and determine all the dependencies needed to make this class function.</figcaption></figure><h3>Whats inside a Container?</h3><p>Have you ever debugged an container and looked inside? You should, it is incredibly fascinating! A container is made up of two main functional parts: I have heard them called many things, in Windsor they are Services and Components. In AutoFac they are Sources and Registrations. I am sure there are many more definitions, but the concept is the same across containers.</p><p><strong>Services / Sources: </strong><em>The “contracts” for constructing an object, the life-cycle of the object, how it is disposed, and what dependencies that object has.</em></p><p><strong>Components / Registrations: </strong><em>The physical instances of objects constructed by a Service/Source.</em></p><h3>Life-cycles: The circle of life…</h3><p>When working with a container, you get a really cool feature called Life-cycles. This allows you to control how an object is constructed, how it is distributed, and when it is disposed. The three main types are…</p><p><strong>Singleton: </strong><em>Singleton lifetime services are once and every request will use the same instance.</em></p><p><strong>Transient: </strong><em>Transient lifetime services are created each time they’re requested. This lifetime works best for lightweight, stateless services.</em></p><p><strong>Scoped: </strong><em>Scoped lifetime services are created per request.</em></p><h3>Service Locator (anti)Pattern</h3><p><em>There are a ton of articles that break this down better than I could, so in the interest of focus for this article, I will only bullet point my main concerns on the pattern.</em></p><ul><li>Conceals the dependencies of a class</li><li>Conceals the construction of nested dependencies</li><li>Makes mocking quite hard!</li></ul><h3>Property Injection (anti)Pattern</h3><p><em>There are a ton of articles that break this down better than I could, so in the interest of focus for this article, I will only bullet point my main concerns on the pattern and supply an alternative.</em></p><ul><li>Conceals the dependencies of a class</li><li>Conceals how a property is hydrated</li><li>Allows engineers to overwrite a property that was constructed via Property Injection</li><li>Makes mocking quite hard!</li></ul><p>Alternatives? <em>Use a dependency resolver.</em> In some cases, you cannot use constructor injection and must use another pattern. Many containers including the .net core container supply you with a dependency resolver for this reason.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/847/1*a0ocRxF9t7AzmFTKKpn05g.png" /><figcaption><strong>Example</strong>:<em> In .net mvc, ActionFilters are singleton, and if you inject transient objects into them, the scope of those are locked until the process terminates and the singleton is disposed. In .net core webapi, middleware supports construct injection, so you will not have to deal with this issue, but its a great example.</em></figcaption></figure><h3>Preferred Containers</h3><p>I prefer AutoFac as my container of choice. I generally stay away from containers that “auto-wiring” items for you in an attempt to help you out. These can slow down your container, for example automatically registering classes for you can slow down the init of the container, OR worse… Make resolving super slow because of the many items within it. I really prefer explicit registration of items in a container so I know exactly what is in the container. When using Assembly Scanning, be as specific as possible or you may accidentally do this.</p><p>Really, the pattern should more or less apply to any container you chose and vary in functionality. Start of with something that you are familiar with and then branch out.</p><h3><strong>Conclusion</strong></h3><p>Dependency Injection should be an every day part of your development life. It was one of those “no turning back” moments for me. This pattern can be used to develop easy to understand architectures, super lean services, or solutions where everything is tied together for the engineer. You can use your container to control what engineers how and where engineers can construct classes. Dependency is a great pattern I think everyone should learn, and encourage others to learn.</p><p>When an engineer finds a solution easy to work with or simple to understand; feel proud and happy. But when that same engineer wants to dig deeper and learn more and challenge themselves; That is the best feeling in the world.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=54898b6f18f5" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>