<?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: Carlos Vega</title>
    <description>The latest articles on DEV Community by Carlos Vega (@veglos).</description>
    <link>https://dev.to/veglos</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%2F554267%2F4b719edb-1d42-4689-a70a-a6ebcabdbdb7.jpeg</url>
      <title>DEV Community: Carlos Vega</title>
      <link>https://dev.to/veglos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/veglos"/>
    <language>en</language>
    <item>
      <title>Simple SOLID</title>
      <dc:creator>Carlos Vega</dc:creator>
      <pubDate>Sun, 30 Jan 2022 19:01:25 +0000</pubDate>
      <link>https://dev.to/veglos/simple-solid-195i</link>
      <guid>https://dev.to/veglos/simple-solid-195i</guid>
      <description>&lt;p&gt;From by blog at &lt;a href="https://veglos.github.io/posts/simple-solid/"&gt;https://veglos.github.io/posts/simple-solid/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Single-Responsibility Principle&lt;/li&gt;
&lt;li&gt;Open-Closed Principle&lt;/li&gt;
&lt;li&gt;Liskov Substitution Principle&lt;/li&gt;
&lt;li&gt;Interface Segregation Principle&lt;/li&gt;
&lt;li&gt;Dependency Inversion Principle&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. Single-Responsibility Principle &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;There should never be more than one reason for a class to change.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Violation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* This class has two reasons to change: it's properties and storing data in the database */&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_repository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;LastName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_repository&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"SQLServer"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="cm"&gt;/* Saving in SQLServer*/&lt;/span&gt;    
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_repository&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"MongoDB"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="cm"&gt;/* Saving in MongoDB*/&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Database not supported"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Compliance
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* This class now cares only about it's properties*/&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;LastName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* this class only cares about storing data in the database*/&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomerRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CustomerRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="n"&gt;_repository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_repository&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"SQLServer"&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="cm"&gt;/* Saving in SQLServer*/&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_repository&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"MongoDB"&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="cm"&gt;/* Saving in MongoDB*/&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Database not supported"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Open-Closed Principle &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Software entities (classes, modules, functions, etc.)&lt;br&gt;
should be open for extension, but closed for&lt;br&gt;
modification. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Violation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailNotifier&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* Notify via e-mail */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SMSNotifier&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* Notify via SMS */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AlertManager&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SendNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;notifiers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* WARNING: New notifiers cannot be added without modifying this module */&lt;/span&gt;
        &lt;span class="k"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;notifier&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;notifiers&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;notifier&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
                &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"Email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
                    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;EmailNotifier&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"SMS"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
                    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sms&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SMSNotifier&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="n"&gt;sms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Compliance
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Notifier&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailNotifier&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Notifier&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* Notify via e-mail */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SMSNotifier&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Notifier&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* Notify via SMS */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WhatsAppNotifier&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Notifier&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* Notify via WhatsApp */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AlertManager&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SendNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Notifier&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;notifiers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* New notifiers can be added without modifying this module */&lt;/span&gt;
        &lt;span class="k"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;notifier&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;notifiers&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="n"&gt;notifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Liskov Substitution Principle &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Functions that use pointers or references to base&lt;br&gt;
classes must be able to use objects of derived classes&lt;br&gt;
without knowing it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Violation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;Connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Table&lt;/span&gt; &lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OracleRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDatabaseRepository&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;Connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* Connect to the database */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt; &lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* fetch table and return it*/&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SQLServerRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDatabaseRepository&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;Connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* Connect to the database */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt; &lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* fetch table and return it*/&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* Imagine MongoDB support was added later in the application: */&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MongoDBRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;Connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* Connect to the database */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt; &lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* MongoDB does not have Tables!! */&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDatabaseRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;   
        &lt;span class="cm"&gt;/* WARNING: If the MongoDBRepository object is passed as a parameter, calling GetTable() will break the application.
        And we cannot check here if the type is either OracleRepository or SQLServerRepository because that would violate the Open-Closed Principle */&lt;/span&gt;      
        &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Compliance
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;Connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;    
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IRelationalDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Table&lt;/span&gt; &lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;    
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OracleRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRelationalDatabaseRepository&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;Connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* Connect to the database */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt; &lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* fetch table and return it*/&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SQLServerRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRelationalDatabaseRepository&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;Connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* Connect to the database */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt; &lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* fetch table and return it*/&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MongoDBRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;Connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* Connect to the database */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IRelationalDatabaseRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* Now we are safe from exceptions, because every instance of IRelationalDatabaseRepository must handle the GetData method.*/&lt;/span&gt;
        &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Interface Segregation Principle &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;clients should not be forced to depend upon interfaces&lt;br&gt;
that they do not use.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Violation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Table&lt;/span&gt; &lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cm"&gt;/* Imagine MongoDB support was added later in the application: */&lt;/span&gt;
    &lt;span class="n"&gt;Collection&lt;/span&gt; &lt;span class="nf"&gt;GetCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;collectionName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SQLServerRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt; &lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* fetch table and return it*/&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Collection&lt;/span&gt; &lt;span class="nf"&gt;GetCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;collectionName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* 
           Method GetCollection is being forced on this class.
           SQLServer does not have Collections! 
        */&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* Imagine MongoDB support was added later in the application: */&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MongoDBRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt; &lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* 
           Method GetTable is being forced on this class.
           MongoDB does not have Tables! 
        */&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Collection&lt;/span&gt; &lt;span class="nf"&gt;GetCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;collectionName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* fetch collection and return it*/&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Compliance
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* Split the IDatabaseRepository interface between IRelationalDatabaseRepository and INonRelationalDatabaseRepository so no implementation is forced to handle methods it doesn't need.*/&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IRelationalDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Table&lt;/span&gt; &lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;INonRelationalDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Collection&lt;/span&gt; &lt;span class="nf"&gt;GetCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;collectionName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SQLServerRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRelationalDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt; &lt;span class="nf"&gt;GetTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* fetch table and return it*/&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MongoDBRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;INonRelationalDatabaseRepository&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Collection&lt;/span&gt; &lt;span class="nf"&gt;GetCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;collectionName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* fetch collection and return it*/&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Dependency Inversion Principle &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;a. high level modules should not depend upon low&lt;br&gt;
level modules. both should depend upon abstractions.&lt;/p&gt;

&lt;p&gt;b. abstractions should not depend upon details. details&lt;br&gt;
should depend upon abstractions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Violation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomerRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CustomerRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="n"&gt;_repository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;

        &lt;span class="cm"&gt;/* WARNING: The high level module CustomerRepository DEPENDS on the low level modules SQLServerRepository */&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_repository&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"SQLServer"&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SQLServerRepository&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="cm"&gt;/* Saving in SQLServer*/&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Database not supported"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Compliance
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IDatabaseRepository&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SQLServerRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDatabaseRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="cm"&gt;/* Saving in SQLServer*/&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomerRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IDatabaseRepository&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CustomerRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDatabaseRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="n"&gt;_repository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/* Now the high level module CustomerRepository and the low level modules SQLServerRepository and MongoDBRepository DEPEND on the abstraction IDatabaseRepository */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;        
        &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>oop</category>
      <category>programming</category>
      <category>c</category>
    </item>
    <item>
      <title>An Authentication &amp; Authorization Microservice with Clean Architecture</title>
      <dc:creator>Carlos Vega</dc:creator>
      <pubDate>Wed, 10 Nov 2021 14:58:38 +0000</pubDate>
      <link>https://dev.to/veglos/an-auth-microservice-with-clean-architecture-1d5p</link>
      <guid>https://dev.to/veglos/an-auth-microservice-with-clean-architecture-1d5p</guid>
      <description>&lt;p&gt;From my blog at &lt;a href="https://veglos.github.io/posts/dotnet-auth-microservice-with-clean-architecture/" rel="noopener noreferrer"&gt;https://veglos.github.io/posts/dotnet-auth-microservice-with-clean-architecture/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code of this project is available at &lt;a href="https://github.com/veglos/dotnet-auth-microservice" rel="noopener noreferrer"&gt;https://github.com/veglos/dotnet-auth-microservice&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;




&lt;ol&gt;
&lt;li&gt;A Clean Architecture&lt;/li&gt;
&lt;li&gt;The Hexagonal Architecture&lt;/li&gt;
&lt;li&gt;
The Design

&lt;ol&gt;
&lt;li&gt;Use Cases&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

The Auth Microservice

&lt;ol&gt;
&lt;li&gt;What about an API Gateway?&lt;/li&gt;
&lt;li&gt;OAuth 2.0, OpenID Connect, and Json Web Token&lt;/li&gt;
&lt;li&gt;Access Token vs Refresh Token&lt;/li&gt;
&lt;li&gt;JWT, JWS, and JWE&lt;/li&gt;
&lt;li&gt;How do other microservices know the Access Token is legit?&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

The Project Structure

&lt;ol&gt;
&lt;li&gt;Auth.Domain&lt;/li&gt;
&lt;li&gt;Auth.Application&lt;/li&gt;
&lt;li&gt;Auth.Infrastructure&lt;/li&gt;
&lt;li&gt;Auth.API&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. A Clean Architecture &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;




&lt;p&gt;In 2012 Robert C. Martin published a blog article called &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;The Clean Architecture&lt;/a&gt; where he wrote about the common features of different systems, like independence of the framework, independence of the database, independence of the UI, etc. Then in 2017 Martin published the book &lt;a href="https://www.amazon.com/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164" rel="noopener noreferrer"&gt;Clean Architecture&lt;/a&gt; that elaborate a further analysis on how a good architecture should be, but most importantly «why».&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fclean-architecture.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fclean-architecture.jpg" alt="/clean-architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1.1: Robert C. Martin's Clean Architecture Diagram&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The Hexagonal Architecture &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;




&lt;p&gt;The Hexagonal Architecture was created by Alistair Cockburn in 2005. He has a complete explanation in &lt;a href="https://alistair.cockburn.us/hexagonal-architecture/" rel="noopener noreferrer"&gt;his site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also known as the Ports &amp;amp; Adapters architecture pattern, it focuses on the &lt;a href="https://en.wikipedia.org/wiki/Dependency_inversion_principle" rel="noopener noreferrer"&gt;Dependency Injection (DI) principle&lt;/a&gt; in order to&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;delay the decision of what technology implementation to use, and&lt;/li&gt;
  &lt;li&gt;change technology implementations later easily&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This pattern relies mainly on four concepts: primary port, primary adapter, secondary port, and secondary adapter. They can be found with different names in literature. See table 2.1.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Primary Port&lt;/th&gt;
&lt;th&gt;Primary Adapter&lt;/th&gt;
&lt;th&gt;Secondary Port&lt;/th&gt;
&lt;th&gt;Secondary Adapter&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Incoming Port&lt;/td&gt;
&lt;td&gt;Incoming Adapter&lt;/td&gt;
&lt;td&gt;Outgoing Port&lt;/td&gt;
&lt;td&gt;Outgoing Adapter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Driving Port&lt;/td&gt;
&lt;td&gt;Driving Adapter&lt;/td&gt;
&lt;td&gt;Driven Port&lt;/td&gt;
&lt;td&gt;Driven Adapter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input Port&lt;/td&gt;
&lt;td&gt;Input Adapter&lt;/td&gt;
&lt;td&gt;Output Port&lt;/td&gt;
&lt;td&gt;Output Adapter&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Table 2.1: Different names for port and adapters according to different literature&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ports&lt;/strong&gt; -both primary and secondary- are just the interfaces that declare what the implementation must do. Conversely, &lt;strong&gt;Adapters&lt;/strong&gt; -both primary and secondary- are the respective implementations of the ports.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Primary&lt;/strong&gt; represents a mean to «run» or «drive» the application. It could be a request to get/send data to/from the app or to start a background process. A primary port shows to the «outside world» how the application can be called. On the other hand, &lt;strong&gt;Secondary&lt;/strong&gt; represents a mean for the application to interact with resources, like calling a web service or fetching data from a database.&lt;/p&gt;

&lt;p&gt;In summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Primary Port:&lt;/strong&gt; Interface exposed by the application for it to be called.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Primary Adapter:&lt;/strong&gt; Implementation of the Primary Port to call the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secondary Port:&lt;/strong&gt; Interface exposed by the application for external resources to be called.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secondary Adapter:&lt;/strong&gt; Implementation of the Secondary Port to access resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I made the diagram shown in figure 2.1 to illustrate the difference.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fhexagonal-architecture.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fhexagonal-architecture.jpg" alt="/hexagonal-architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 2.1: Hexagonal Architecture diagram&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The Design &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;




&lt;p&gt;From the previous diagrams in figure 1.1 and figure 2.1, I designed the diagram displayed in figure 3.1. I kept the same color scheme to identify the boundaries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fclean-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fclean-1.jpg" alt="/clean-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 3.1: Auth microservice architecture model&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The solution is composed of four projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auth.Domain:&lt;/strong&gt; Contains the enterprise business rules in classes (mostly &lt;a href="https://en.wikipedia.org/wiki/Plain_old_CLR_object" rel="noopener noreferrer"&gt;POCO&lt;/a&gt;). It doesn't have any dependencies except the .NET Framework itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auth.Application:&lt;/strong&gt; Contains the application business rules, represented by the use cases. Depends only on the Auth.Domain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auth.Infrastructure:&lt;/strong&gt; Contains the specific implementation of services and repositories. Depends on the Auth.Application and Auth.Domain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auth.API:&lt;/strong&gt; Contains the controllers to be called by the user, and in turn, call the use cases. It also hosts the Microsoft Dependency Injection Container which explains why it depends not only on Auth.Domain and Auth.Application, but also Auth.Infrastructure *.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;*&lt;em&gt;note&lt;/em&gt;: It is possible to avoid the Auth.Infrastructure dependency by creating a DI Container project. I believe it's not worth the inconvenience in this situation, but it's totally possible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fclean-2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fclean-2.jpg" alt="/clean-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 3.2: Dependency relationship between projects&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1. Use Cases &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Use cases are the heart of the application, they execute the business rules. Here are some quotes from Uncle Bob:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Indeed, this is the first concern of the architect, and the first priority of the architecture. The architecture must support the use case&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;– Martin, R.C. (2017). In Chapter 16 Independence. Clean Architecture (p. 148). Prentice Hall.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The most important thing a good architecture can do to support behavior is to clarify and expose that behavior so that the intent of the system is visible at the architectural level&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;– Martin, R.C. (2017). In Chapter 16 Independence. Clean Architecture (p. 148). Prentice Hall.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;[...], use cases are narrow vertical slices that cut through the horizontal layers of the system. Each use case uses some UI, [...] business rules [...], and some database functionality&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;– Martin, R.C. (2017). In Chapter 16 Independence. Clean Architecture (p. 152). Prentice Hall.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fclean-3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fclean-3.jpg" alt="/clean-3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 3.3: Use cases cutting through the horizontal layers&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Our Auth microservice has two main use cases: Login use case and Refresh Token use case.&lt;/p&gt;

&lt;p&gt;Given the login credentials, the Login use case returns an Access Token and a Refresh Token. The Access Token can be used by the client application to access other microservices that trust the Auth microservice. The Refresh Token is needed to get a new Access Token. More on this later.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The Auth Microservice &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;




&lt;p&gt;An Auth Microservice is a centralized authority that grants authentication and authorization (Auth for short) to a user to allow her/him access to a resource provided by other systems (i.e. other microservices) that trust said authority.&lt;/p&gt;

&lt;p&gt;Nowadays it is imperative for most microservices to have authentication and authorization, and while it is possible to implement them in every microservice, it is far more convenient to rely on an Auth Microservice. We don't want to login (ask for credentials) in every single microservice. Let the microservice focus on the scope they were meant to handle, nothing more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fauth-microservice.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fauth-microservice.jpg" alt="/auth-microservice"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 4.1: The Auth Microservice handles the authentication and authorization of the user/client&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1. What about an API Gateway? &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://microservices.io/patterns/apigateway.html" rel="noopener noreferrer"&gt;The API Gateway&lt;/a&gt; may or may not handle authentication and authorization, and it can have more responsibilities than that, like response caching, circuit breaker, load balancing, etc., but it's main purpose is to be a single entry point to the entire system.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2. OAuth 2.0, OpenID Connect, and Json Web Token &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;There are Id Tokens and Access Tokens. Id Tokens hold information about who the user is (claims), and &lt;strong&gt;the intended recipient is the client application&lt;/strong&gt; (i.e. to show "Welcome Carlos!", etc.). &lt;br&gt;
On the other hand, Access Tokens hold information about what can be done (scopes) in a resource (i.e. fetch the user's photos, etc.), therefore &lt;strong&gt;the intended recipient of such token is the user's resource&lt;/strong&gt;. Figure 5.1 depicts how an Access Token works.&lt;/p&gt;

&lt;p&gt;The Id Token is defined by the &lt;a href="https://openid.net/connect/" rel="noopener noreferrer"&gt;OpenID Connect Specification&lt;/a&gt;, whereas the Access Token is defined by the &lt;a href="https://oauth.net/2/" rel="noopener noreferrer"&gt;OAuth 2.0 Specification&lt;/a&gt;. The former must be sent in a &lt;a href="https://jwt.io/" rel="noopener noreferrer"&gt;JSON Web Token (JWT)&lt;/a&gt; format, the latter can be any string, including JWT.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It is not the scope of this article to deal with the Client App (or any front-end project for that matter), hence I dealt mostly with Access Tokens, not so much ID Tokens.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fauth-sequence.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fauth-sequence.jpg" alt="auth-sequence"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 4.2: Sequence diagram of the process of authorization by Access Token&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4.3 Access Token vs Refresh Token &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;There is a third and last type of token called the Refresh Token.&lt;/p&gt;

&lt;p&gt;As previously mentioned, the Access Token allows the user to access a resource, however it has a short lifespan, and depending on the system, it could last between 5 minutes and 1 hour. This is important because if for some reason the Access Token get stolen, the attacker could only make use of it for a short time.&lt;/p&gt;

&lt;p&gt;However, we don't want to keep asking the user for her/his credentials in order ot get a new Access Token every 5 minutes. That's why we issue a Refresh Token, which has a long lifespan, usually between 1 day and 1 week, and can be used by the client application to get a brand new Access Token without prompting the user with a login screen every time.&lt;/p&gt;

&lt;p&gt;But could the Refresh Token also be stolen? Yes, but since a Refresh Token is assigned to a single user, it can be disabled and be forced to re-login again, preventing the attacker from getting a new Access Token.&lt;/p&gt;

&lt;p&gt;Access Tokens cannot be disabled, unless we change the Private-Public key pairs, but that would disable every single token in circulation.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.4. JWT, JWS, and JWE &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Prabath Siriwardena does a wonderful explanation in his article &lt;a href="https://medium.facilelogin.com/jwt-jws-and-jwe-for-not-so-dummies-b63310d201a3" rel="noopener noreferrer"&gt;JWT, JWS and JWE for Not So Dummies!&lt;/a&gt;. Basically, as the &lt;a href="https://www.rfc-editor.org/rfc/rfc7519" rel="noopener noreferrer"&gt;RFC 7519&lt;/a&gt; says, JWT is a mean of representing claims (or scopes) between two parties, but the actual implementation occurs as a JSON Web Signature (JWS) or a JSON Web Encryption (JWE), or a combination of both. JWS encodes and signs the payload, whereas JWE encrypts the payload.&lt;/p&gt;

&lt;p&gt;For this project I used JWT with JWS, and while it is possible to implement your own JWT library, it is highly recommended to use an already tested and popular library like the ones listed on &lt;a href="https://jwt.io/libraries" rel="noopener noreferrer"&gt;https://jwt.io/libraries&lt;/a&gt;. I used the Microsoft's System.IdentityModel.Tokens.Jwt library.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.5. How do other microservices know the Access Token is legit? &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;There are two possible ways for a microservice to recognize that the Access Token received is actually from the Auth Microservice and not a malicious impostor (and/or that the payload has not been modified). The two ways are by a &lt;strong&gt;shared secret key&lt;/strong&gt; or by a &lt;strong&gt;public-private key pair&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A shared secret key is used when the Auth Microservice uses &lt;strong&gt;symmetric&lt;/strong&gt; cryptography to sign the payload. Another microservice would need to know the same secret key (hence a shared secret) in order to verify if the payload is true.&lt;/p&gt;

&lt;p&gt;A public-private key pair is used when the Auth Microservice uses asymmetric cryptography to sign the payload, that is, it still requires a private key to sign it, but the verification can be done with just the public key, which as its name implies, it can be publicly distributed to the world without compromising the private key.&lt;/p&gt;

&lt;p&gt;It is safer to keep the signing key (private key) in the Auth Microservice and only share the public key, no matter how much you trust the other microservices. That's why this project uses &lt;strong&gt;asymmetric&lt;/strong&gt; cryptography.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fasymmetric.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fveglos.github.io%2Fassets%2Fimg%2F2021-11-08-dotnet-auth-microservice-with-clean-architecture%2Fasymmetric.jpg" alt="asymmetric"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 4.3: Simplified example of asymmetric cryptography&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. The Project Structure &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;




&lt;p&gt;As stated before, the solution is made of four projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.1. Auth.Domain &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

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

Auth.Domain /
├─ User.cs
├─ RefreshToken.cs
├─ Claims.cs


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

&lt;/div&gt;

&lt;p&gt;The first and most important layer. It contains the enterprise business rules. It is quite simple because the RefreshToken class and the Claims class are part of the User class, so it could have been just a single .cs file.&lt;/p&gt;

&lt;p&gt;The scope of the Auth Microservice is narrow. The domain classes are enough to encompass the authentication and authorization.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.2. Auth.Application &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

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

Auth.Application /
├─ Enums
├─ Exceptions
├─ Ports /
   ├─ Repositories
   ├─ Services
├─ UseCases
   ├─ CreateUser /
   ├─ Login /
   ├─ RefreshToken /
   ├─ SignOut /
   ├─ IUseCase.cs
   ├─ Request.cs
   ├─ Response.cs


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

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Just as the plans for a house or a library scream about the use cases of those buildings, so should the architecture of a software application scream about the use cases of the application&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;– Martin, R.C. (2017). In Chapter 21 Screaming Architecture. Clean Architecture (p. 196). Prentice Hall.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Auth.Application holds the "screaming" part of the architecture that tells us what the system it's about. Just by looking at the UseCase folder, it is apparent what the application does: Create a user, Log in, refresh a token, and sign out.&lt;/p&gt;

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

Auth.Application /
├─ Ports /
   ├─ Repositories /
      ├─ IAuthRepository.cs
   ├─ Services /
      ├─ IAuthTokenService.cs
      ├─ ICryptographyService.cs


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

&lt;/div&gt;

&lt;p&gt;If we zoom in a little bit, the Ports folder declares the interfaces of the implementations that the use cases will need in order to be executed. That means &lt;strong&gt;all ports here are secondary/output ports&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.3. Auth.Infrastructure &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

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

Auth.Infrastructure /
├─ Repositories /
   ├─ MongoDB /
      ├─ Scripts /
      ├─ AuthRepository.cs
      ├─ MongoDbSettings.cs
├─ Services /
   ├─ Cryptography
      ├─ CryptographyService.cs
   ├─ Jwt
      ├─ JwtService.cs
      ├─ JwtSettings.cs



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

&lt;/div&gt;

&lt;p&gt;This project contains the secondary adapters. Basically, every external infrastructure that is not fundamental for the behavior of the application, like third-party services or databases. For example, changing from SQL Server to PostgreSQL or MongoDB does not change the behavior of the application (asi in, the use cases).&lt;/p&gt;

&lt;h3&gt;
  
  
  5.4. Auth.API &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

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

Auth.API /
├─ Controllers /
   ├─ AuthController.cs
├─ Program.cs
├─ Startup.cs
├─ appsettings.json


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

&lt;/div&gt;

&lt;p&gt;This layer in particular has two roles. &lt;/p&gt;

&lt;p&gt;First, it is an HTTP API primary adapter: It receives HTTP requests and converts them into request objects that the application can process.&lt;/p&gt;

&lt;p&gt;Second, it is a &lt;a href="https://en.wikipedia.org/wiki/Dependency_injection" rel="noopener noreferrer"&gt;Dependency Injection Container&lt;/a&gt; that knows how to instantiate and configure objects in runtime in order to be injected in the application when it requires it. This project uses the Microsoft.Extensions.DependencyInjection library. It is common practice to do this in an ASP.NET Core Web API project, since most application will only have HTTP Requests as inputs, so it's easier to do this right here rather than creating another project for the DI Container. This is the reason why the Auth.API project depends on the Auth.Infrastructure project *.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*note: If the DI Container where in another project, for instance an Auth.DIContainer project, then the Auth.API project wouldn't need to depend on the Auth.Infrastrutcure project. It's just a matter of convenience why I did it this way.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Conclusion &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;




&lt;p&gt;&lt;em&gt;There's no silver bullet&lt;/em&gt;. There are many ways to implement a clean architecture, and many more ways to keep improving it forever. The important thing here is to grasp and understand the concepts and know how to identify them. &lt;/p&gt;

&lt;p&gt;We must have a clear-cut boundary between layers and the direction of dependencies. The implementation of new features immediately &lt;em&gt;"smell weird"&lt;/em&gt; when the boundaries are not taken into consideration. For example, if the Auth.Application requires to import a third-party library to access an Excel document then there is a clear violation of the dependency rule (the application cannot depend on the infrastructure), and necessary measures are required to correct it.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>architecture</category>
      <category>dotnet</category>
      <category>security</category>
    </item>
  </channel>
</rss>
