Blog
Blog HelionBlog HelionBlog HelionBlog Helion
  • Artykuły
  • Autorzy
  • Recenzje
  • Konkursy

Mnemonik SOLID — O jak Open/Closed Principle

    Blog.helion.pl Artykuły Mnemonik SOLID — O jak Open/Closed Principle
    NastępnyPoprzedni

    Mnemonik SOLID — O jak Open/Closed Principle

    By Helion | Artykuły, Programowanie | Brak komentarzy | 1 lipca, 2016 | 0

     

    Tworząc oprogramowanie, bardzo często stoimy przed dylematem: czy pisać kod szybko, czy porządnie. Oczywiście, o ile tylko mamy możliwość, wybierajmy tę drugą opcję, jednak taka decyzja generuje nowy problem, ponieważ na wczesnym etapie procesu wytwarzania oprogramowania trudno jest określić dokładny kierunek rozwoju.

    Dlatego też projektując oprogramowanie, nie musimy od razu rozplanowywać wszystkiego, ale powinniśmy zadbać o to, by tworzony przez nas kod był łatwo rozszerzalny zarówno dziś, jak i w przyszłości. Innymi słowy, warto sięgnąć po znane praktyki i dobre wzorce specjalistów, którzy przed podobnymi wyzwaniami stanęli już wcześniej.

     

    W poprzednim poście zrobiłem krótki wstęp do mnemonika Solid oraz szerzej opisałem pierwszą z jego reguł, czyli Single Responsibility Principle. Dziś chcę zająć się zasadą Open/Closed, która w pewnym sensie narzuca kolejną technikę, którą powinniśmy uwzględnić we wspomnianym wcześniej procesie planowania.

     

    Open/Closed Principle

    Zasada Open/Closed mówi o tym, że powinniśmy projektować oprogramowanie w taki sposób, by w razie konieczności jego rozwoju nie było potrzeby modyfikacji istniejącego kodu. Taki problem można rozwiązać na wiele sposobów, m.in. wykorzystując wzorzec projektowy Dekorator, jednak jest to tylko pewien środek zaradczy po wystąpieniu problemu. W praktyce powinniśmy działać od samego początku, tworząc oprogramowanie, którego kod wykorzystuje interfejsy we wszystkich (lub w zdecydowanej większości) klasach funkcjonalnych.

     

    Być może zastanawialiście się czasem, czy interfejsy, które pozostawiamy w kodzie, nie są nadmiarowe, ponieważ w wielu przypadkach i tak tworzymy dla nich jedną implementację. Takie wątpliwości pojawiają się szczególnie w pierwszych latach programistycznej tułaczki, dlatego warto sobie uzmysłowić, że nasz kod ulega ciągłej zmianie. Jeśli zawczasu zadbamy o odpowiednie interfejsy przy wszelakich klasach funkcyjnych, to istnieje spora szansa, że w przyszłości unikniemy refaktoryzacji działającego i przetestowanego kodu — i przy okazji napiszemy kod zgodny z regułami sztuki 🙂

    Poniżej mały przykład, który wykorzystuje kod powstały w ostatnim tekście.

     

    Przykład praktyczny

    W poprzednim wpisie [link] przygotowaliśmy mały generator raportów, który wykorzystywał pliki PDF. Wyobraźmy sobie teraz, że przyszło nowe wymaganie do systemu, które zakłada konieczność generowania plików CSV. Jeśli spojrzymy na kod z poprzedniego przykładu, to szybko okaże się, że spełnia on zarówno zasadę SRP, jak i częściowo OCP. Kluczem do sukcesu jest w tym przypadku interfejs IFileWriter:

     

     
    
    
    public interface IFileWriter
    {
    	void Open();
    	void WriteData(IEnumerable<string> data);
    	void Close();
    }
    

     

    który nie jest ukierunkowany na żaden konkretny format plików. Bardzo łatwo możemy więc teraz dodać klasę CsvFileWriter, która będzie zgodna z Open/Closed Principle. Nowa klasa rozszerzy możliwości systemu i jednocześnie nie wpłynie na istniejące funkcje generatora PDF-ów. Poniżej kod źródłowy:

     

     
    
    public class CsvFileWriter : IFileWriter
    {
    	public CsvFileWriter(string filePath)
    	{
    		Console.WriteLine($"CSV file with path: {filePath}");
    	}
    	public void Open()
    	{
    		Console.WriteLine("CSV file open");
    	}
    
    	public void WriteData(IEnumerable<string> data)
    	{
    		Console.WriteLine($"Write {data.Count()} records to CSV file");
    	}
    
    	public void Close()
    	{
    		Console.WriteLine("CSV file close");
    	}
    }
    

     

    Niestety, jest jedna rzecz, która w wyjściowym kodzie mogłaby być zrobiona lepiej. Jest nią fakt, że w kodzie klasy ReportGenerator zapięliśmy się na klasę PdfFileWriter. Oczywiście, tak jak pisałem w poprzednim tekście, można było ten problem rozwiązać za pomocą IoC na poziomie klasy, ale można też wprowadzić stosunkowo małą modyfikację na poziomie metody. Poniżej zmodyfikowany kod:

     

     
    
    public class ReportGenerator
    {
    	public void GenerateReport(IFileWriter fileWriter, DateTime date)
    	{
    		IDatabaseManager databaseManager = new MyDatabaseManager();
    		var reportData = databaseManager.GetReportData(date);
    
    		fileWriter.Open();
    		fileWriter.WriteData(reportData);
    		fileWriter.Close();
    	}
    }
    

     

    Na dobrą sprawę nie dokonaliśmy tutaj żadnej rewolucji. Nasza klasa wciąż generuje raport, jedynie zmieniliśmy miejsce tworzenia generatora plików.

    Zmiany w tym miejscu wymuszają również modyfikację klasy Program. Poniżej jej nowy kod, który uwzględnia generowanie raportów dla dwóch formatów plików:

     

     
    
    public class Program
    {
    	public static void Main(string[] args)
    	{
    		IFileWriter pdfFileWriter = new PdfFileWriter("myreport.pdf");
    		IFileWriter csvFileWriter = new CsvFileWriter("myreport.csv");
    
    		ReportGenerator reportGenerator = new ReportGenerator();
    
    		DateTime dt = new DateTime(2016, 05, 9);
    		reportGenerator.GenerateReport(pdfFileWriter, dt);
    		reportGenerator.GenerateReport(csvFileWriter, dt);
    	}
    }
    

     

    W prosty sposób spełniliśmy założenia Open/Closed Principle i dodaliśmy nową funkcję, która zasadniczo nie wpłynęła na istniejący kod. Oczywiście, nie zawsze uda się w pełni zachować zasady OCP, czy też dowolnej innej reguły Solid, ale mimo wszystko warto o to powalczyć, tworząc oprogramowanie.

    Jerzy Piechowiak

    Altcontroldelete.pl

     

     

     Szukasz książki do C#? Kliknij TU lub zerknij poniżej:

     

     

    .net, altcontroldelete, c#, CSV, design patterns, Jerzy Piechowiak, programista, programowanie, SOLID
    Avatar

    Helion

    Więcej postów od Helion

    Podobne posty

    • Mnemonik SOLID — S jak Single Responsibility Principle

      By Helion | Brak komentarzy

      Bardzo lubię powiedzenie „lepiej nie wymyślać koła od nowa”, ponieważ pasuje do wielu obszarów naszego codziennego życia, w tym programowania. Pisząc kod, bardzo często rozwiązujemy problemy, nad którymi ktoś już wcześniej pracował.

    • Wzorzec projektowy adapter

      By Jerzy Piechowiak | Brak komentarzy

      Bardzo trudno jest napisać fragment kodu, o którym moglibyśmy powiedzieć, że jest idealny. Praktycznie niemożliwe jest zrobienie takiej rzeczy za pierwszym razem.

    • Wzorzec projektowy strategii

      By Jerzy Piechowiak | Brak komentarzy

      Programowanie, wbrew obiegowym opiniom, nie jest aż takie trudne. Wypuszczenie nawet prostych aplikacji mobilnych czy stron nie wymaga dzisiaj dużych nakładów sił. Największym problemem jest napisanie takiego kodu, który będzie łatwo rozszerzalny i będzie miałCzytaj więcej…

    • Wzorce projektowe — null object

      By Jerzy Piechowiak | Brak komentarzy

      „Object reference not set to an instance of an object” — taki, pojawiający się w najmniej oczekiwanym momencie komunikat to zmora każdego programisty C#. Przyczyna jest zawsze taka sama, a jest nią wyjątek NullReferenceException.

    • Mnemonik SOLID – D jak Dependency Inversion Principle

      By Jerzy Piechowiak | Brak komentarzy

      Przyszła pora na ostatnią literkę z mnemonika SOLID, ale to wcale nie oznacza, że jest ona najmniej ważna. D rozwijane jest jako Dependency Inversion Principle co tłumaczone jest jako Zasada Odwrócenia Zależności.

    NastępnyPoprzedni

    Znajdź post

    Bądźmy w kontakcie

    Książka dnia

    Encyklopedia elementów elektronicznych. Tom 1. Rezystory, kondensatory, cewki indukcyjne, przełączniki, enkodery, przekaźniki i tranzystory

    Autor: Charles Platt

    Cena: 48.30 zł 69.00 zł
    (Cena e-booka: zł zł)

    O 21zł taniej!

    kup teraz

    Najnowsze wpisy

    • Błyskawiczny kurs pisania skryptów powłoki
    • Przykładowa aplikacja webowa zaimplementowana w ASP .NET Core
    • Wprowadzenie do .NET Core: instalacja, konfiguracja, pierwsza aplikacja w systemie Linux
    • Grupa Helion zaprasza na szkolenia stacjonarne!
    • Hello World! Czym jest programowanie?

    Tagi

    .net agile altcontroldelete asp.net c# czysty kod debugowanie design patterns e-biznes emarketing Google Google Analytics hacking Jerzy Piechowiak kod kodowanie Krzysztof Marzec książka Maciej Dutko magazyn programista Magdalena Daniłoś marketing MVVM onepress organizacja czasu praca prograista programista programowanie prokrastynacja rafał kocisz reklama rozwój software craftsman SOLID startup techniki programowania testowanie video marketing visual studio WPF wzorce projektowe youtube zarządzanie czasem zarządzanie projektami

    Archiwum

    • Lipiec 2017
    • Czerwiec 2017
    • Maj 2017
    • Kwiecień 2017
    • Marzec 2017
    • Luty 2017
    • Styczeń 2017
    • Grudzień 2016
    • Listopad 2016
    • Październik 2016
    • Wrzesień 2016
    • Lipiec 2016
    • Czerwiec 2016
    Blog wydawnictwa
    Informatyka w najlepszym wydaniu
    Strona wydawcy:
    www.helion.pl
    Księgarnia Helion.pl
    Nowości
    Bestsellery
    Promocje
    Bądźmy w kontakcie:
    Chcesz zostać autorem?
    Masz pytania do redakcji?
    Napisz do nas »
    • Artykuły
    • Autorzy
    • Recenzje
    • Konkursy
    Blog Helion