<?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>DEV Community: onetomkenny</title>
    <description>The latest articles on DEV Community by onetomkenny (@onetomkenny).</description>
    <link>https://dev.to/onetomkenny</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%2F550215%2F21b78ce2-ad79-4626-9f9e-e1ce241f5636.png</url>
      <title>DEV Community: onetomkenny</title>
      <link>https://dev.to/onetomkenny</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/onetomkenny"/>
    <language>en</language>
    <item>
      <title>Implementing A Repository Layer With Inverted Dependency</title>
      <dc:creator>onetomkenny</dc:creator>
      <pubDate>Fri, 08 Jan 2021 01:13:44 +0000</pubDate>
      <link>https://dev.to/onetomkenny/implementing-a-repository-layer-with-inverted-dependency-16k1</link>
      <guid>https://dev.to/onetomkenny/implementing-a-repository-layer-with-inverted-dependency-16k1</guid>
      <description>&lt;h2&gt;
  
  
  The Continuing Story Of How Dependency Injection Was Implemented In A Large Brownfield Platform
&lt;/h2&gt;

&lt;p&gt;This is the second journal entry &lt;a href="https://dev.to/onetomkenny/the-journey-of-a-brownfield-monolith-towards-solid-koo"&gt;in a series&lt;/a&gt; that documents the conversion of a brownfield monolith towards SOLID programming principles.  See the original post for the story of our motivation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/onetomkenny/introducing-dependency-injection-to-a-large-brownfield-application-289g"&gt;The last post&lt;/a&gt; covered how to take code written directly against a volatile dependency (database) and break out a Service class that implements an Interface so that the consuming code can work against that abstraction as opposed to the implementation.   &lt;/p&gt;

&lt;p&gt;This is useful because it creates seams in your code that make it easier (possible) to do unit testing and to substitute new implementations later on.&lt;/p&gt;

&lt;p&gt;If you have a good understanding of &lt;a href="https://dev.to/onetomkenny/introducing-dependency-injection-to-a-large-brownfield-application-289g"&gt;the previous post&lt;/a&gt;, then what comes next will be easier to follow.  &lt;/p&gt;

&lt;p&gt;This post continues our implementation of “The first six chapters” of the book &lt;a href="https://www.amazon.com/Dependency-Injection-Principles-Practices-Patterns/dp/161729473X" rel="noopener noreferrer"&gt;Dependency Injection – Patterns Principles And Practices&lt;/a&gt; by Steven Van Deursen and Mark Seemann.    Some of what follows will seem a bit radical but for reasons outlined in the last post, I found I had a high degree of confidence in what that book was telling me.   &lt;/p&gt;

&lt;p&gt;As I joked to my boss later on, “I did 90% of what the book advised and then for the other 10% I did it my way and the result is I love 90% of the work I've done and hate the other 10%”.  &lt;/p&gt;

&lt;h2&gt;
  
  
  A Refresher...
&lt;/h2&gt;

&lt;p&gt;At the end of the last post, the code related to Company was organized like this in the business (domain) layer project:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fly9l5zoy6j957wyh7a4o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fly9l5zoy6j957wyh7a4o.png" alt="Alt Text" width="234" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Load method in the CompanyRepositoryService class looks like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjoay71g7d2xwvvijjm3q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjoay71g7d2xwvvijjm3q.png" alt="Alt Text" width="520" height="83"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The BuildClassFromProcResults method is something we wrote internally to handle the common task of calling a stored procedure and marshalling the return data into a class instance.&lt;br&gt;&lt;br&gt;
The fragment CompanySP.GetCompanyInfoSP(companyID) is a call to a method in our DataAccessLayer project where we define all these stored procs.&lt;/p&gt;

&lt;p&gt;The first problem with our solution was that our DataAccessLayer project didn't really represent a layer in the architectural sense.  It wasn’t doing much at all except holding stored proc definitions.  Your situation is probably different but the point here is that “Projects that are named like Architectural layers” can be deceptive.&lt;/p&gt;

&lt;p&gt;Anyway, the Business Layer has a &lt;em&gt;&lt;strong&gt;dependency&lt;/strong&gt;&lt;/em&gt; on the DataAccessLayer (the second needs to Build before the former can be built).   The Dependency Injection book makes the argument for &lt;em&gt;&lt;strong&gt;inverting&lt;/strong&gt;&lt;/em&gt; that dependency to make loose coupling a part of your development process.  You can read their arguments for this on pages 48-49 of the book.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Our Reasoning For An Inverted Dependency
&lt;/h3&gt;

&lt;p&gt;For us the decision to do follow the author's lead was made in spite of our view that we would not likely have use for the options this creates:   &lt;/p&gt;

&lt;p&gt;We knew that we were going through the entire business layer anyway and decided it would be best to add 10% more work and risk to avoid the hazard of realizing later that we should have gotten fully modern when we had the chance.&lt;/p&gt;

&lt;p&gt;When we thought about the testing requirements that we were signing up for by rifling through the critical business layer code, it seemed like any errors introduced by reworking the related database code would be discovered by the manual testing we already had to do anyway.&lt;/p&gt;

&lt;p&gt;I'm happy to report that this was a solid assumption on our part.  In fact once we got going, the conversions were quite smooth: &lt;/p&gt;

&lt;p&gt;Conversions on Monster Classes typically create between zero and two bugs that are fairly obvious and are quickly discovered by testers or other devs and then easily fixed.   No customer facing blowups have occurred because of DI work as yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating The SqlDataRepository Project
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a new SqlDataRepository project for the solution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now move the CompanyRepositoryService.cs file (see the code organization figure above) into the new project.   &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember that the class in this file implements a  ICompanyRepositoryService interface.  The definition for that interface will stay in the business layer project.  This moves us towards the goal of the business layer not needing to have an implementation of the ICompanyRepositoryService methods to build.&lt;/p&gt;

&lt;p&gt;At this point, we took the opportunity to make a new implementation of the &lt;em&gt;&lt;strong&gt;ReaderTools&lt;/strong&gt;&lt;/em&gt; code noted earlier on.    This code uses the &lt;em&gt;&lt;strong&gt;DbDataReader&lt;/strong&gt;&lt;/em&gt; internally and because we have a goal of removing all “Database” references from the business layer we decided to wrap this with a more generic “RepositoryReader” service. &lt;/p&gt;

&lt;p&gt;The particulars are outside the scope of this blog, but this snippet shows a piece of the code for illustration:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxzcljbdgi0xuix7bt4x3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxzcljbdgi0xuix7bt4x3.png" alt="Alt Text" width="316" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We did something similar making a general ManagedTransaction service to handle SQL Transactions.   The result being that the business layer only knows there is an IManagedTransaction interface that defines methods implementing some transaction manager.&lt;/p&gt;

&lt;p&gt;Your situation and goals will determine how far you want to go with this, but in our case, the interfaces are all defined in the business layer and the implementations are all inside the SqlDataRepository layer.   In principle, we could move over to Oracle database or an Azure data store and the business layer would be indifferent.&lt;/p&gt;

&lt;p&gt;Finally, you could define all these repository interfaces in a third project in the hopes of making your business and repository layers build in parallel.  Where you land on the tradeoff between solution complexity and build speed (not to mention “coolness”) is up to you but hopefully you can see how this inverted dependency approach creates all sorts of opportunity.&lt;/p&gt;

&lt;h2&gt;
  
  
  DI Containers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;“OK, but once you’ve built the solution, how do you connect the code in the business layer that uses repository interfaces to their implementation?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another question you might have had reading part 1 is “How/where do you manage all these dependencies that you are passing into these services you are creating?”&lt;/p&gt;

&lt;p&gt;This is where a DI Container comes in.   During the &lt;a href="https://dotnetrocks.com/?show=1603" rel="noopener noreferrer"&gt;.NET Rocks&lt;/a&gt; interview with Steven Van Deursen that I mentioned &lt;a href="https://dev.to/onetomkenny/the-journey-of-a-brownfield-monolith-towards-solid-koo"&gt;in the introductory post&lt;/a&gt; he advises trying something called “Pure DI” at first.   This is the approach we took in part 1.   You just manage creating all these dependencies by hand and see how it goes until you start to see why you (probably) need a DI container.&lt;/p&gt;

&lt;h2&gt;
  
  
  SimpleInjector
&lt;/h2&gt;

&lt;p&gt;We selected SimpleInjector as our DI Container.  Steven is the maintainer of SimpleInjector but the Dependency Injection book also covers several alternatives in detail in the later chapters.   &lt;/p&gt;

&lt;p&gt;The thing I liked most about SimpleInjector is that while it could be made to do almost anything that competing containers could do, it came with limited out-of-the-box capabilities. &lt;strong&gt;This is no accident:&lt;/strong&gt;   SimpleInjector is a tool used by people who’ve “Tried it all” and have a good idea about what works and what gets you into trouble.&lt;/p&gt;

&lt;p&gt;For example, Property Injection is not supported by default.   You can enable this, but the book will explain why you probably shouldn’t.   Other DI Containers will just cheerfully show you how to do things you wouldn’t likely do if you knew more.  This gets back into that earlier .NET Rocks interview that so impressed me.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The idea is that the tool pushes the developer to "fall into the pit of success".&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  If You Decide To Try SimpleInjector..
&lt;/h2&gt;

&lt;p&gt;Grab the SimpleInjector Nuget package and add it to your solution.  It will need to be in the projects that instantiate services (likely your business (domain) layer and your UI layer).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0e702dryoz8h308oalld.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0e702dryoz8h308oalld.png" alt="Alt Text" width="767" height="206"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Make your SqlRepository project depend on the Business Layer project
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Right click on your Solution in Solution Explorer and select Common Properties -&amp;gt; Project Dependencies.   Select the SqlRepository project and click the checkbox so that it depends on BusinessLayer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxoj9rexizbvoapazuwkp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxoj9rexizbvoapazuwkp.png" alt="Alt Text" width="781" height="357"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then inside the SqlRepository project add a reference to the business layer project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flrbj0x6z21k0ufnw4ggq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flrbj0x6z21k0ufnw4ggq.png" alt="Alt Text" width="348" height="50"&gt;&lt;/a&gt; &lt;br&gt;
Pro-tip: Configure VS to build all projects.   &lt;/p&gt;

&lt;h3&gt;
  
  
  A Minor Pitfall
&lt;/h3&gt;

&lt;p&gt;By default VS only looks at building the Startup project and any projects that it depends on. Since SqlRepository is none of these, it will often not get built when you “Build” or even “Rebuild solution”.  This can lead to frustrating runtime errors.  &lt;/p&gt;

&lt;p&gt;Did I mention that with DI you trade compile time errors for runtime errors?  This is a result of coding against an abstraction (interface) instead of an implementation.  The DI Container doesn't provide the implementation until runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To configure VS to build all projects:&lt;/strong&gt;&lt;br&gt;
Tools &amp;gt; Options &amp;gt; Projects And Solutions&lt;br&gt;
Uncheck “Only build startup projects and dependencies on Run”&lt;/p&gt;

&lt;p&gt;This should not adversely effect build times because VS already checks to see if anything in a project changed before it triggers a build.&lt;/p&gt;

&lt;p&gt;We added a postbuild step to our Repository project so that it copied the built dll into the bin folder where the other dlls are all sent:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6a4nhvyuey13bbv2y3x4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6a4nhvyuey13bbv2y3x4.png" alt="Alt Text" width="667" height="556"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;For reference, the string is “copy /Y "$(TargetPath)" "$(SolutionDir)\bin\$(TargetFileName)"”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now for the last big setup step:&lt;/strong&gt;   We need to setup our DI Container with registrations for the services we built in Part 1.&lt;/p&gt;

&lt;p&gt;Here is an example class including a &lt;strong&gt;GetInstance()&lt;/strong&gt; method that returns an object implementing a specified interface using a DI Container:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhkt4xx9x8w5ecb24uysn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhkt4xx9x8w5ecb24uysn.png" alt="Alt Text" width="567" height="483"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;First notice there is a “container” property which is a static variable.   This class is using a singleton pattern.   The container property will be setup one time by the first consumer to ask for it and then after that the same container will always be used.&lt;/p&gt;

&lt;p&gt;Notice the get accessor calls lazy.Value.   The Lazy&amp;lt;&amp;gt; code just below that works to ensure that the setup is only run once and only by one thread (Lazy blocks all other threads that make a concurrent call until the setup is complete).&lt;/p&gt;

&lt;p&gt;The CreateContainerAndRegisterDependencies() method is where the setup action is.   First we instantiate our container, and then call some methods to actually register types.   Then we call  Verify() which is a facility that SimpleInjector offers to validate your setup.&lt;/p&gt;

&lt;p&gt;Now lets take a look inside the RegisterDomainDependencies() method:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fakp9nmsmybdye0u8b9jo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fakp9nmsmybdye0u8b9jo.png" alt="Alt Text" width="758" height="81"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;These lines are registering (in the DI container) an implementation for each of the ICompanyService and ICompanyCheckerService interfaces.   This will mean that a consumer asking the DIContainer for an ICompanyService will get a CompanyService instance and that a request for ICompanyCheckerService will return a CompanyCheckerSerice instance.&lt;/p&gt;

&lt;p&gt;The Lifestyle specification at the end refers to the length of time the object should live.   See the Dependency Injection book or the SimpleInjector documentation for more on this.   We use Singleton to indicate that the same instance should always be returned to each caller for maximum performance.  Transient could be used to have the container create a new instance for each caller.&lt;/p&gt;

&lt;p&gt;Next lets look inside RegisterRepositoryDependencies()&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faeand6c95tv0gj3f5uk5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faeand6c95tv0gj3f5uk5.png" alt="Alt Text" width="707" height="193"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;This one is a bit more involved.  Remember how we set the business layer to build without building SqlRepository first?  We could do that because we inverted the dependency.  But that means that we need to examine the compiled SqlRepository.dll at runtime and find the implementation of our interface.&lt;/p&gt;

&lt;p&gt;Your paths may differ but the example above is consistent with the postbuild step we added to copy the dll into the bin folder&lt;/p&gt;

&lt;h2&gt;
  
  
  “This doesn’t look very scalable!”
&lt;/h2&gt;

&lt;p&gt;You may notice the code above has us hand coding various type and implementation pairings.   For real world scenarios, you can express logic that helps SimpleInjector perform auto-registration of items in bulk.&lt;/p&gt;

&lt;p&gt;The particulars will vary for your application but on our platform we handled bulk repository registrations by creating a base IRepositoryService Interface from which every other Repository interface inherits.  Then we wrote a LINQ query to get a list of all the derived interface/class pairings and feed that to Simpleinjector all at once.&lt;/p&gt;

&lt;p&gt;For example, here is the code we use to handle the Repository registrations in all its intimidating glory:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe4xp00ymi0z71bnl1lc2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe4xp00ymi0z71bnl1lc2.png" alt="Alt Text" width="690" height="439"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There are other ways to do this.&lt;/strong&gt; You can check the documentation for SimpleInjector or the Dependency Injection book when designing your own auto registration code. Chapter 14 covers auto-registration with SimpleInjector.&lt;/p&gt;

&lt;p&gt;We chose to use interfaces (instead of a naming convention for services) because the interfaces are code which gives you compiler checking along with "referenced by" tooling in VS that allow you to trace every services place in the DI system.  We have a base IDomainService for business layer services to distinguish those from repository services.&lt;/p&gt;

&lt;p&gt;That AttemptSafeRegistration() method contains code that examines the service being registered and compares it to the Lifestyle requested to see if they match.   Its not even close to failsafe but can at least stop developers from registering a service with public properties as a Singleton lifestyle (which wouldn’t play well with concurrent usage).&lt;/p&gt;

&lt;h2&gt;
  
  
  Payday finally comes:
&lt;/h2&gt;

&lt;p&gt;Finally, we can see an example of how we can use the DI Container to provide us with an implementation of the interface we coded against at runtime.&lt;/p&gt;

&lt;p&gt;Here is a snippet of how you get the CompanyRepositoryService by specifying an ICompanyRepositoryService at runtime:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frsig7rvdawptl7zg0g7q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frsig7rvdawptl7zg0g7q.png" alt="Alt Text" width="497" height="42"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course the only reason to have one of these around in our example is to make a CompanyService and the reason that exists is to make a CompanyCheckerService.  Thanks to the DI Container, we can get this all done in one line:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs8afda8qmmhq1cs6xyyv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs8afda8qmmhq1cs6xyyv.png" alt="Alt Text" width="585" height="92"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That one-liner is considerably more interesting!   The DIContainer didn’t just make a CompanyCheckerService for you.  It saw that the lone constructor for CompanyCheckerService required a CompanyService so it made one of those.  Then it made a CompanyRepositoryService since one of those is required to construct a CompanyCheckerService.&lt;/p&gt;

&lt;p&gt;So the DI Container discovers and manages all these mappings for you.   This is how you can use a few lines of code to create complex objects at runtime but still write code that is testable because the lone constructors mentioned earlier all take interfaces which can be mocked at test time.&lt;/p&gt;

&lt;h2&gt;
  
  
  A tortured word about Service Locator
&lt;/h2&gt;

&lt;p&gt;The authors of the Dependency Injection book have a lot to say about the Service Locator Pattern which &lt;a href="https://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/" rel="noopener noreferrer"&gt;they consider to be an Anti-Pattern&lt;/a&gt;.  I will give my “Real World Brownfield” opinion on the matter.&lt;/p&gt;

&lt;p&gt;The first and ultimate truth for us as a brownfield platform is that “Service Locator is already everywhere”, and converting portions of it to DI makes this more obvious but on its own does nothing to fix this, nor does it make things worse.  &lt;/p&gt;

&lt;p&gt;The second problem we have is that we happen to be a classic asp.net WebForms based platform and Webforms was clearly not designed with DI in mind.   The first edition of the Dependency Injection book has a chapter about about applying the concept of Composition Root to a WebForms application and its almost comically difficult to implement.   We would never put that much effort into hundreds of Web Forms when that effort could be put into just converting the web forms into something more modern.&lt;/p&gt;

&lt;p&gt;The Dependency Injection Book makes additional arguments about Service Locator leading to code that hides its dependencies.  This can be especially troublesome if you are creating a redistributable library since your users have no way of knowing what services are required when they use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Approach
&lt;/h2&gt;

&lt;p&gt;We are building a Platform where all devs have access to all code so hidden dependencies are more of an annoyance than a devastating problem.   Furthermore, devs can (and do) make an effort to push their service locator instances up the stack towards the main entry point of the code.   In this way, things slowly evolve in the direction of better until we move onto a more modern request handler than WebForms.&lt;/p&gt;

&lt;p&gt;In the end, its important to remember that implementing DI in a BrownField applicaton doesn't create the Service Locator so much as reveal it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stumbling point – Unit Testing
&lt;/h2&gt;

&lt;p&gt;Since the purpose of the DI Container is to supply your application with access to development or production versions of volatile dependencies, you probably don’t want container code run during your unit tests to build those very dependencies.  This is something that can happen easily in a platform full of legacy code where team members are already taxed trying to develop good test writing skills as they rework legacy code to make it testable.&lt;/p&gt;

&lt;p&gt;We briefly tried out the idea of having the DI Container return “default testing mocks” when this situation came up.    Even as we created that system, it felt like the real answer was just to get better at method and test writing so that we didn’t need to do this.  Indeed that bit of Lazy&amp;lt;&amp;gt; code above was first developed to deal with the multithreaded nature of the Test Running in Visual Studio.   &lt;/p&gt;

&lt;h2&gt;
  
  
  Our "Probably Wrong Turn" With Default Testing Dependencies
&lt;/h2&gt;

&lt;p&gt;We used the Moq library and reflection based code to just mock up every interface for which the DI Container would register a production implementation and then used Moq again to define default return values for various common return types.&lt;/p&gt;

&lt;p&gt;The resulting tests didn't run dreadfully slowly, but you could feel the extra 20% time lag by the time we hit 500 tests and we knew we didn’t want to pay that penalty for 5000 tests.   Also it made the tests harder to read and reason about since they counted on this secret behind the scenes behavior that developers had to keep in mind.&lt;/p&gt;

&lt;p&gt;Finally, when we looked into removing default testing mocks, we found that only a few of our tests relied on them being there and by then we know how to rewrite them into better tests anyways.&lt;/p&gt;

&lt;p&gt;So, I would suggest you don’t use the DI Container to manage creation of default testing mocks.  As always your miles may vary.  Perhaps you have mission critical monster methods that you need to wrap in some big ugly acceptance style unit tests before you feel brave enough to start refactoring them into something more manageable.   Just be sure you have a good reason before you do it is my advice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Environment Detection
&lt;/h2&gt;

&lt;p&gt;In any event, you will probably want to have some code in your DI Container setup to detect that you are being asked to provide dependencies in a test environment.&lt;/p&gt;

&lt;p&gt;A snippet from our platform code is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0cge52v966uis47rpb2s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0cge52v966uis47rpb2s.png" alt="Alt Text" width="793" height="158"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;The worker process name for a test environment will differ depending on what you use.   The first two constants refer to the VS Test Runner and the last refers to a command line test runner that our Continuous Integration server uses for running tests.&lt;/p&gt;

&lt;p&gt;In our case, we throw an exception when running under a test environment since unit tests should be mocking their own dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Between this and the previous post, we have a big picture overview of how to convert the business (domain) and repository layers of a brownfield application to feature Dependency Injection for the handling of dependencies like Database access.   &lt;/p&gt;

&lt;p&gt;The resulting Repository Service is a true architectural layer and the traditional dependence of the domain layer upon it is inverted so that it depends on the domain layer.&lt;/p&gt;

&lt;p&gt;This state of affairs provides the Platform with new code seams that make unit testing practicable and allows for developers to substitute new dependency implementations with little to no changes required in consumer code.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Introducing Dependency Injection To A Large Brownfield Application</title>
      <dc:creator>onetomkenny</dc:creator>
      <pubDate>Thu, 07 Jan 2021 18:21:51 +0000</pubDate>
      <link>https://dev.to/onetomkenny/introducing-dependency-injection-to-a-large-brownfield-application-289g</link>
      <guid>https://dev.to/onetomkenny/introducing-dependency-injection-to-a-large-brownfield-application-289g</guid>
      <description>&lt;p&gt;This is the first journal entry &lt;a href="https://dev.to/onetomkenny/the-journey-of-a-brownfield-monolith-towards-solid-koo"&gt;in a series&lt;/a&gt; that documents the conversion of a brownfield monolith towards SOLID programming principles.  See the original post for the story of our motivation.&lt;/p&gt;

&lt;h1&gt;
  
  
  Proselytizing The Dependency Injection book
&lt;/h1&gt;

&lt;p&gt;The book &lt;a href="https://www.amazon.com/Dependency-Injection-Principles-Practices-Patterns/dp/161729473X" rel="noopener noreferrer"&gt;Dependency Injection – Patterns Principles And Practices&lt;/a&gt; by Steven Van Deursen and Mark Seemann is not the only book used to inform our move towards DI and Unit Testing but it’s the most important one.  Even if building greenfield, being informed by someone who has seen it all will help you to get the most out of these approaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spoiler Alert: We Only Did The First Six Chapters
&lt;/h2&gt;

&lt;p&gt;The first six chapters of the book make the arguments for DI and provide a solid overall view of how to construct your business (domain) and repository layers.   The rest of the book focuses on tooling and, later, a very abstract Command/Query interface based approach.  If we had been building Greenfield I think we would have given that Command/Query approach a serious look but it was simply too radical for us to attempt on a brownfield project where cross-cutting-concerns were already implemented in a very different way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Did
&lt;/h2&gt;

&lt;p&gt;The book advocates that any method making use of volatile dependencies should be in a “Service” class and those dependencies should be injected via constructor.&lt;/p&gt;

&lt;p&gt;The biggest pitfall for us was making baby steps towards this goal when we should have made the big leap from the get-go. &lt;/p&gt;

&lt;p&gt;With the benefit of hindsight and experience, I will show you how you can break the important considerations down into manageable pieces that you won't have to go back and fix again later on.&lt;/p&gt;

&lt;p&gt;Lets say that, like us, you have a business (domain) model expressed via classes that typically contain a bunch of properties, some “simple” helper methods and then methods that access the database.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For example, consider this class which models information about and actions on a Company:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiqomae1am15h466f3sto.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiqomae1am15h466f3sto.png" alt="Alt Text" width="541" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It contains properties that model what a Company is. It also contains a Load() method that makes a call to a SQL database.  The IDBReader interface up top obligates the class to implement a BuildFromDBReader() method which is our standard way of reading database return columns into the properties of the class.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There are some problems with this class from a “Testability” standpoint:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, the Load() method is static and makes a direct call to a database (hidden inside BuildClassFromProcResults).  This will make any method that uses it difficult/impossible to unit test effectively.&lt;/p&gt;

&lt;p&gt;Consider a method in some other class enforcing the requirement that a Company has a valid name:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2gswgezno9pwzh8xup2c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2gswgezno9pwzh8xup2c.png" alt="Alt Text" width="437" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How do you write a unit test for this method when it contains that call to Company.Load()?   Inside the method we know there is a stored proc call that requires a real database behind it.   &lt;/p&gt;

&lt;p&gt;You could pass a Company instance into the method, but then that method is liable to end up untestable for the same reasons that this one is.  &lt;/p&gt;

&lt;p&gt;Looking back at the Company class again, the COLUMNS region is our way of tracking the names of the returned SQL columns from the Load() method.  But this means SQL specific implementation details are part of the class.   Even if you never plan on changing DB providers, why have those details cluttering up the class?  If you take pride in naming things well (which you should) then why would something called Company model aspects of a specific database implementation?&lt;/p&gt;

&lt;h2&gt;
  
  
  “OK, but still, it doesn’t look that bad”.
&lt;/h2&gt;

&lt;p&gt;That was our feeling for a long time.   But we started to notice some things over time.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There are often lots &lt;em&gt;&lt;strong&gt;(lots)&lt;/strong&gt;&lt;/em&gt; of database related methods that start piling up in a class.&lt;/li&gt;
&lt;li&gt;For brevity, the example contains almost no “Business logic” code but once you add say five methods to express the behaviors of “Company” (which is after-all the point of having a business class), you are well on your way to “monster class” territory.&lt;/li&gt;
&lt;li&gt;So while this example looks pretty benign, you will eventually write 100 of these classes with all manner of interdependencies.&lt;/li&gt;
&lt;li&gt;Then when you need to add a feature or fix a bug, you will find yourself tripping over database specific code that has nothing directly to do with your problem but which is mixed up in the code you need to alter.
&lt;/li&gt;
&lt;li&gt;Throw in some caching, logging and security and you’ve built a puzzle the next guy will love spending whole days pondering.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Separation Of Concerns
&lt;/h2&gt;

&lt;p&gt;The big picture problem is that concerns need to be separated out.  The Company class should ideally tend towards being a &lt;a href="https://en.wikipedia.org/wiki/Plain_old_CLR_object" rel="noopener noreferrer"&gt;POCO class&lt;/a&gt;:  It should define the properties and behaviors of a Company but not include any database specific information (or information related to any other volatile dependency like caching, logging, security etc).&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1:   Create a “Service” class.
&lt;/h3&gt;

&lt;p&gt;Lets start by breaking up the Company class towards this ideal of a POCO object.  We do this by moving all the database specific code out into a CompanyService class:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F69ngbv9hoemswk6l08fa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F69ngbv9hoemswk6l08fa.png" alt="Alt Text" width="544" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice the Load method is no longer static and the Update method has a Company parameter which contains the Company info being sent to the database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This leaves our original class a little lighter:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk00x8zx2ma45nkes880p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk00x8zx2ma45nkes880p.png" alt="Alt Text" width="455" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And CompanyChecker needs a bit of work to get the build working again:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffvh2wdr5n3hv8y8eb6hw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffvh2wdr5n3hv8y8eb6hw.png" alt="Alt Text" width="481" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So what have we accomplished?   Nothing substantial yet, but we can now focus on that Load method as a Dependency and Inject that into the CompanyChecker code instead of making a new one inside the method.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating A Dependency
&lt;/h3&gt;

&lt;p&gt;The first step is to make the CompanyService methods implement an interface.  This will give us the  abstraction we need to support Mocking later on.&lt;/p&gt;

&lt;p&gt;Start out by defining an ICompanyService interface in a new file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbsqwjnfvkx5zn2cg51ul.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbsqwjnfvkx5zn2cg51ul.png" alt="Alt Text" width="254" height="26"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It may seem like overkill to put this in its own file, but we have found through bitter experience that things tend to grow until the “one file” you are using becomes unwieldy.   If you are going to take a shortcut, putting too much in a file is probably the one you will come to regret the least as it’s the easiest to fix.&lt;/p&gt;

&lt;p&gt;The next step is to make CompanyService implement this interface:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fax93kcssdo6munlqkz39.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fax93kcssdo6munlqkz39.png" alt="Alt Text" width="333" height="19"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, we need to define an interface method for each of the methods that do something with the database.  The easiest way to do this is to right click on the method and use the Quick Refactorings in VS to “pull” the method up into the interface:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5ufwcs5mrzpqimhzs3jm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5ufwcs5mrzpqimhzs3jm.png" alt="Alt Text" width="800" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now your interface looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftde1wx6g8l4thx7n7cpc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftde1wx6g8l4thx7n7cpc.png" alt="Alt Text" width="365" height="69"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets go back to CompanyChecker and alter it so that we Inject our CompanyService into it.  This will look familiar if you have read the Dependency Injection book.  We choose to use Constructor injection as per the advice of that book.  Method injection is also an option though it can often be cumbersome for consumers in a real world application.   Property injection is discouraged as it makes the resulting code harder to read and reason about – see sections 4.2 through 4.4 of the book for extensive discussion on these considerations which you want to understand before you go designing anything big.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What we end up with is this:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F59a1yrcmbudcu1pva3c2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F59a1yrcmbudcu1pva3c2.png" alt="Alt Text" width="473" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CompanyChecker is rechristened CompanyCheckerService to reflect the fact that it makes use of volatile dependencies (of course, it always did - we just didn’t see it before). It implements an ICompanyCheckerService interface that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fknql9ro3j2frtyp3411u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fknql9ro3j2frtyp3411u.png" alt="Alt Text" width="425" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code inside the DI region (shown below) defines the _companyService property now used inside the CheckCompanyName method.&lt;/p&gt;

&lt;p&gt;The complete class looks like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyd53uoeqrgpkbrn76s6o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyd53uoeqrgpkbrn76s6o.png" alt="Alt Text" width="485" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For reference, here is what our folder structure for Company related code now looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb9qe6549vqucx41ah3xe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb9qe6549vqucx41ah3xe.png" alt="Alt Text" width="221" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Suddenly we are in a position to write a unit test.&lt;/p&gt;

&lt;p&gt;Our Platform uses xUnit (and the VS Test Runner) along with Moq as our mocking library.  Choosing a good mocking library is important.  One weak spot that we have noticed in Moq is that its naming conventions make it easy to confuse Mocks with Stubs and Fakes.   Otherwise its working well for us.  You might want to look at FakeItEasy and other tools before you make a choice.&lt;/p&gt;

&lt;p&gt;So far, we elect to put our unit tests in their own class in the same file with a naming convention of Test[ClassName].&lt;/p&gt;

&lt;p&gt;The complete code to test the CheckCompanyName() method looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz6hfol1ru5536gxmvqck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz6hfol1ru5536gxmvqck.png" alt="Alt Text" width="631" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So [Fact] is the attribute that marks the method as an xUnit test.    The test method name follows the common “Subject Scenario Result” naming scheme.&lt;/p&gt;

&lt;p&gt;The first line uses the Moq library to create a mock object of type ICompanyService.  The second line mocks the Load() method so that it returns a Company with a value of null in its Name property.&lt;/p&gt;

&lt;p&gt;The next line passes this mock into a new CompanyCheckerService.  Finally we call CheckCompanyName() and verify that an exception is thrown.&lt;/p&gt;

&lt;p&gt;There is a lot more to Unit Testing than what is shown here and in the future I plan to write about our experiences in that area.   But in the end, writing good unit tests is a craft in and of itself.   &lt;/p&gt;

&lt;h2&gt;
  
  
  TDD Digression
&lt;/h2&gt;

&lt;p&gt;I should point out that if you were writing the functionality of “Company” from scratch, you could approach writing the CheckCompanyName() method with TDD coding practices.  Notice that once you have that ICompanyService interface defined, you could write the unit test above by mocking up the Load behavior before you even wrote an implementation for Load().   The idea is that you write your unit test so that it fails, and then work on CheckCompanyName() until the test passes.  &lt;/p&gt;

&lt;p&gt;OK, so now we have a method that needs info from the database covered by a concise unit test that won’t break if you add new properties or methods to the Company class.  But Company still contains all that DBReader stuff plus those Database Column constants.  What now?&lt;/p&gt;

&lt;p&gt;Now we take the next logical step which is to create a Repository service where all the database specific code resides, moving it out of Company.  That Repository service will then be injected into CompanyService.&lt;/p&gt;

&lt;p&gt;Just as we did with CompanyService, we create a CompanyRepository class implementing an ICompanyRepositoryInterface.&lt;/p&gt;

&lt;p&gt;Snapshots of the results look like this:&lt;/p&gt;

&lt;p&gt;ICompanyRepository definition (in it’s own file):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fftjx4pvop3qg0dbycy1d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fftjx4pvop3qg0dbycy1d.png" alt="Alt Text" width="416" height="87"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CompanyRepositoryService (implements Load and Update and has a method implementing our own BuildFromDBReader code to translate database return info into property values):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdhjywsaqpca5u9ikyzvt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdhjywsaqpca5u9ikyzvt.png" alt="Alt Text" width="512" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CompanyService now has an ICompanyRepositoryService object injected via the constructor which it uses for its Load and Update functionality:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F93wfpageojm8q7qhn9sj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F93wfpageojm8q7qhn9sj.png" alt="Alt Text" width="547" height="393"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Finally, we come to the Company class to find it stripped of everything except its properties and “simple” helper methods that don't require access to volatile dependencies:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8b5stxhay14hjpip6dyy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8b5stxhay14hjpip6dyy.png" alt="Alt Text" width="461" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, the files for all of this are currently organized like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl305gk6qi3de8y26deok.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl305gk6qi3de8y26deok.png" alt="Alt Text" width="234" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  “Hey, so CompanyService is nice, but what’s it really doing?”
&lt;/h2&gt;

&lt;p&gt;When converting existing code over DI, it’s best to take a series of baby steps to keep trouble to a minimum.  There are three reasons for the existence of CompanyService:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In real life a method like Update() might invalidate a cache or perform logging in addition to using the database.  The Load method might run security checks to see if the signed in user is allowed to call the method.   These will involve use of volatile dependencies that would also probably be injected into CompanyService alongside the RepositoryService.&lt;/li&gt;
&lt;li&gt;Indeed, a method like Update might involve so many dependencies or so much logic that you will find yourself breaking out a CompanyUpdateService just for that purpose.  What I’m showing you here is “an approach to developing” rather than “the answer”.&lt;/li&gt;
&lt;li&gt;Finally, when I was working on our Platform I took a shortcut early on based on my reading of the Dependency Injection book that got me into a bit of trouble:  I just renamed the original Company class to be CompanyService and then injected a RepositoryService into it, keeping the Load and Update methods where they were while moving the database specific code into the RepositoryService.   But then I found that I couldn’t new() up a CompanyService instance without feeding all sorts of dependencies into the constructor even if I didn’t want to call methods that used them.  I later had to go plowing through all my shiny new DI code to break out service classes to resolve these problems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Honestly, its tedious breaking everything out in a way that feels almost compulsive, but separation of concerns will free you in the long run.   The time you spend searching for the code that does something will be more than offset by the confusion you wont experience because its not all mixed up with other concerns in some monster method or class.  And as my boss points out, breaking the contents of 400 files out into 2000 files doesn’t really create a searching problem in VS.   If you haven’t done it yet try “ctrl-t” in VS and start typing a class, method or file name.  There is no search time penalty when you implement a more verbose approach.&lt;/p&gt;

&lt;p&gt;You may have read blog posts to the effect of “new() is Evil” or “Toxic”.   Those articles argue that new()-ing up objects with volatile dependencies will get you into trouble.   Our unfinished example is already in a state where you can new up a Company object without any “evil” or “toxicity” because now it’s just a simple class containing code that is true to its name.  You can also New() up the services provided you pass them the appropriate dependencies.  How you get those dependencies and where you set them up is a problem to be discussed in a future post.&lt;/p&gt;

&lt;p&gt;In fact, many important design considerations that are covered in the Dependency Injection book are glossed over here.   You should read at least the first six chapters of that book.  &lt;strong&gt;Like, now.&lt;/strong&gt;     &lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/onetomkenny/implementing-a-repository-layer-with-inverted-dependency-16k1"&gt;next post&lt;/a&gt; we will look at getting that RepositoryService into its own project where you are probably already thinking it should be.   Although our platform will probably never replace Microsoft SQL Server, we have an architecture that will eventually tell a reader of our business code next to nothing about the underlying data store (except perhaps the common ID property is a gives away that a Relational Database is involved).&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The Journey Of A Brownfield Monolith Towards SOLID</title>
      <dc:creator>onetomkenny</dc:creator>
      <pubDate>Thu, 07 Jan 2021 18:21:42 +0000</pubDate>
      <link>https://dev.to/onetomkenny/the-journey-of-a-brownfield-monolith-towards-solid-koo</link>
      <guid>https://dev.to/onetomkenny/the-journey-of-a-brownfield-monolith-towards-solid-koo</guid>
      <description>&lt;h1&gt;
  
  
  Our First Thousand Unit Tests...
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;"Wait, we’ve written 1000 Unit tests?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This would have seemed like a ridiculous goal 18 months ago.   Our 19 year old monolith platform created by (on average) four developers was the sort that everyone pretends not to work on these days:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  240,000 lines of C# code, with no unit testing (though we did have other forms of automated acceptance testing and js based unit tests on the front end).
&lt;/li&gt;
&lt;li&gt;  C# code is written directly against volatile dependencies like database and caching.
&lt;/li&gt;
&lt;li&gt;  Subject Matter Experts confidently stride into dark corners of the code whenever there is a problem.
&lt;/li&gt;
&lt;li&gt;  The code is structured enough that non-SMEs can work when SMEs are on vacation even though its slow going. The code is “pretty” though decidedly legacy (as per &lt;a href="https://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052" rel="noopener noreferrer"&gt;Michael C Feathers&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fourth Time's The Charm
&lt;/h3&gt;

&lt;p&gt;Over the years we had made probably three half-hearted attempts at unit testing in the business layer but ran into the same problems that everybody else does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;How to get data into the methods you want to test&lt;/em&gt;&lt;/strong&gt; You’ll try a special database first.  You will grow old trying to keep it in the right state and tests will run glacially slow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Very little of our code featured Abstract, Virtual or Interface based practices.&lt;/em&gt;&lt;/strong&gt; That seemed to leave reflection based testing as an option.  A very non-performant, brittle option that looked best suited to getting code into a test harness for a more aggressive refactoring that ended with more unit test coverage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Our methods were "well written" but contain layers of nested logic.&lt;/em&gt;&lt;/strong&gt;  You can’t easily write a set of concise unit tests for that sort of code and end up confident that you are really testing every logical possibility.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;And lets be honest, our ability to deploy new versions with massive internal changes that don’t cause huge fires proves that we are great developers right?&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Still, you feel growing unease because the application is growing in complexity and it would be nice to hire new people without them having to spend six months learning all the system’s secret handshakes.  &lt;/p&gt;

&lt;p&gt;You know the world has moved on since you left school too.  You could have written off Dependency Injection, Mocking, Unit Testing and Compositional coding approaches as “probably just fads” ten years ago.  &lt;/p&gt;

&lt;p&gt;Maybe…&lt;/p&gt;

&lt;p&gt;But now this is all mainstream stuff with a proven track record and the best developer interview candidates get quiet when you let on that you don’t really do any of that SOLID stuff at your company.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;And There Was Another Problem&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Our business logic was tightly coupled to a number of things that were slipping into legacy status.   Without seams in the code our business and repository logic was mixed up with the implementation details of those components.  Some of them (like Full Framework) were on the list of “Definitely someday we need to deal with that”.   &lt;/p&gt;

&lt;p&gt;But how could we really make progress against something so large when the platform has to add features just to pay the bills today?  And what about all the other dependencies in the meantime?  The thought of a business layer containing nothing but business logic indifferent to the outside world seemed like such a beautiful utopia.&lt;/p&gt;

&lt;p&gt;Growing feelings of long term dread coupled with a change in company ownership created an opportunity to lead an attack on all of these through an initiative creatively called &lt;em&gt;&lt;strong&gt;&lt;em&gt;“Do Unit Testing, But For Real This Time”.&lt;/em&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There was no shortage of good vibes coming from the newer team members, but the rest of us knew how past attempts had gone. We knew it was going to take more than getting everyone to just say they would do things better.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Slow Start...
&lt;/h3&gt;

&lt;p&gt;The most obvious pain point was getting data into the methods we wanted to test.  We already knew we needed to use mocking rather than trying to maintain a slow database.   The major mocking tools and the blogs about Test Driven Development were all talking about Dependency Injection.   There was no shortage of punchy little demos proving just how easy it all was.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;But it wasn’t easy for us because the state of our existing code was nothing like those examples.&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Another problem was that every DI example was introducing considerable amounts of abstraction into examples that started out as some pretty straightforward coding.   It seemed like making the system easier to manage meant you had to make it way more complicated.   Could this be sold to a team already used to doing things “the obvious way”?  &lt;/p&gt;

&lt;p&gt;What about the risks of this bold new direction?  It didn’t seem like you could just break off a little piece from these techniques and then add more later on if it went well.  You had to do them all to write testable code and you had to wrap your head around several new disciplines and integrate them all to have a shot at ending up with something you wanted to work on every day.   &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Who do you trust for good advice?&lt;/em&gt;&lt;/strong&gt;  Can you really bet your architecture on a blog post or a few witty remarks in a stack-overflow comment?&lt;/p&gt;

&lt;h3&gt;
  
  
  Inspiration Comes…
&lt;/h3&gt;

&lt;p&gt;Then I heard a .NET Rocks interview with &lt;a href="https://dotnetrocks.com/?show=1603" rel="noopener noreferrer"&gt;Steven van Deursen&lt;/a&gt; about the tools and practices required to approach Dependency Injection effectively.   This interview was what I had been looking for.  Finally, I was hearing a coherent vision for both the “why” and the “how”.  It made sense.  And it seemed realistic.   &lt;/p&gt;

&lt;p&gt;Steven &lt;a href="https://www.amazon.com/Dependency-Injection-Principles-Practices-Patterns/dp/161729473X" rel="noopener noreferrer"&gt;wrote a book with Mark Seeman&lt;/a&gt; full of the knowledge that comes out of dealing with these issues repeatedly in many organizations in several languages over decades.   The book is quite abstract, but a few reads gave me the confidence to formulate a plan for an “all-in” approach to updating our architecture to something fully modern.&lt;/p&gt;

&lt;p&gt;What really won me over was Steven’s desire to create tools and approaches that &lt;strong&gt;&lt;em&gt;“push the developer to fall into the pit of success”&lt;/em&gt;&lt;/strong&gt;, rather than just demo a bunch of neat ways to do things.&lt;/p&gt;

&lt;p&gt;This blog will be about my experiences, approaches, mistakes and realizations introducing SOLID principles as a main feature of the platform I work on daily.&lt;/p&gt;

&lt;p&gt;I’m ready to write it now because with about 45% of our domain/repository code now based on DI Services and with over 1000 fast running, maintainable, concise, resilient unit tests written (and no signs of slowing down) we know that what we are doing is working.   &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;We are slowly climbing the mountain.&lt;/em&gt;&lt;/strong&gt;   And we are still adding features.   And we are getting better at what we do as a team and as individual developers and this will help our development team attract more fellow travelers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;And honestly, there is a bit of humble bragging here too:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Converting a large monolith to use Dependency Injection in support of Unit Testing is not easy.   I was lucky to be among friends when I took on the task of reworking the entire business and data access layers of our platform and setting coding standards for others to follow.&lt;/p&gt;

&lt;p&gt;Our informal deal was something like, "Everyone makes a good faith effort to follow my lead and I am honest to the point of total humility about what's working and improving what's not working."&lt;/p&gt;

&lt;p&gt;If you are feeling like we were a little while ago, then join us for the journey.  &lt;/p&gt;

&lt;p&gt;The first post is &lt;a href="https://dev.to/onetomkenny/introducing-dependency-injection-to-a-large-brownfield-application-289g"&gt;here.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testdev</category>
      <category>csharp</category>
      <category>dependencyinjection</category>
      <category>solid</category>
    </item>
  </channel>
</rss>
