CI jak Ćwiczenia Dependency Inversion Principle, czyli Zasada odwrócenia zależności

przez | 12 lutego, 2020

Dependency inversion principle — Zasada odwróconej zależności

Wysokopoziomowe moduły nie powinny zależeć od modułów niskopoziomowych, lecz zależność powinna wynikać z abstrakcji.

Bestseller dnia w księgarni Złote Myśli

Jak wykorzystywać w praktyce DIP?

Twórzmy dużo abstrakcyjnych bytów. Każda klasa niech implementuje interfejs lub dziedziczy po klasie abstrakcyjnej. Tworząc oprogramowanie, możemy najpierw stworzyć tylko interfejsy, a dopiero później je zaimplementować.

Pomocne w spełnieniu tej zasady jest przestrzeganie tych reguł:

  • Każda zmienna w klasie jest referencja do abstrakcji.
  • Wszystkie klasy dziedziczą po abstrakcji.
  • Żadna klasy potomna nie przesłania metod z klasy bazowej.
  • Ustawianie zmiennych realizowane jest przez wzorzec fabryki lub wstrzykiwania zależności.

Przykład

Poniżej mamy klasę pokazującą raport. Dane do raportu brane są za bazy danych. Implementacja wygląda następująco:

class Program
   {
       static void Main(string[] args)
       {
 
           var reportImporter = new ReportDatabaseImporter();
           var reportPresenter = new ReportPresenter(reportImporter);
           reportPresenter.ShowReport();
       }
   }
 
   internal class ReportPresenter
   {
 
       private readonly ReportDatabaseImporter importer;
 
 
       public ReportPresenter(ReportDatabaseImporter importer)
       {
           this.importer = importer;
       }
 
       public void ShowReport()
       {
           Console.WriteLine(importer.GetReportData());
       }
   }
 
 
 
   internal class ReportDatabaseImporter
 
   {
       public string GetReportData()
 
       {
           return "Report from Database";
       }
   }

Po jakimś czasie dostaliśmy prośbę o wyświetlanie danych również z pliku Excel w taki sam sposób. Niestety, nie jesteśmy w stanie zrobić tego łatwo. Musimy zmienić klasę prezentującą raport. Takie rozwiązanie pozwala nam dodawać łatwiej kolejne źródła raportu:

using System;
 
namespace SRP.Bad
{
    class Program
    {
        static void Main(string[] args)
        {
            var reportImporter = new ReportDatabaseImporter();
            var reportPresenter = new ReportPresenter(reportImporter);
            reportPresenter.ShowReport();
 
 
 
            var reportImporter2 = new ReportExcelImporter();
            var reportPresenter2 = new ReportPresenter(reportImporter2);
            reportPresenter2.ShowReport();
        }
    }
 
    internal class ReportPresenter : IReportPresenter
    {
        private readonly IReportImporter importer;
 
        public ReportPresenter(IReportImporter importer)
        {
            this.importer = importer;
        }
        public void ShowReport()
        {
            var reportData = importer.GetReportData();
            Console.WriteLine(reportData.GetContent());
        }
    }
 
    internal class ReportDatabaseImporter : IReportImporter
    {
        public IReportData GetReportData()
        {
            return new ReportData("Report from Database");
        }
    }
    internal class ReportExcelImporter : IReportImporter
    {
        public IReportData GetReportData()
        {
            return new ReportData("Report from Excel");
        }
    }
    internal class ReportData : IReportData
    {
        private readonly string content;
 
        public ReportData(string content)
        {
            this.content = content;
        }
        public string GetContent()
        {
            return content;
        }
    }
    internal interface IReportData
    {
        string GetContent();
    }
    internal interface IReportImporter
    {
        IReportData GetReportData();
    }
 
    internal interface IReportPresenter
    {
        void ShowReport();
    }
}

Mamy tutaj dużą liczbę interfejsów. Ułatwiają one jednak rozwój aplikacji oraz testowanie. W testach będziemy mogli pod interfejs podstawić mocka.

Wszystkie posty związane z mini projektem: Poznaj zasady SOLID i OOP:

Źródła

Obraz główny

Materiały

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *