Nie SOLID-nie #02: Open Close Principle

N

Seria zainspirowana bardzo dobrym kursem SOLID od Jarka Stadnickiego, dostępnym na platformie Udemy – SOLID praktyczny kurs

(Nie jest to reklama, ani żadna afiliacja. Wyrażam swoje zdanie 🙂 )

 


Spis postów z serii Nie SOLID-nie:

  1. Nie SOLID-nie #01: Single Responsibility Principle
  2. Nie SOLID-nie #02: Open Close Principle
  3. Nie SOLID-nie #03: Liskov Substitution Principle
  4. Nie SOLID-nie #04: Interface Segregation Principle
  5. Nie SOLID-nie #05: Dependency Inversion Principle

 

Open Close Principle

Reguła Open Close Principle mówi o tym, że klasa powinna być otwarta na rozszerzenia i jednocześnie zamknięta na modyfikacje. Zgodnie z zasadą tego cyklu – „Nie SOLID-nie„, przedstawiam jak może wyglądać klasa napisana wbrew tej regule.

 

Przykład

Skoro ostatnim razem, w przypadku reguły SRP, posłużyłem się przykładową klasą MessageProcessor, tym razem posłużę się przykładową klasą MessageSender. W klasie tej implementuję metodę SendMessage przyjmującą w parametrze obiekt typu IMessage i na podstawie typu tego obiektu, metoda ta realizuje określoną funkcjonalność.

public class MessageSender
    {
        public void SendMessage(IMessage message)
        {
            MailMessage mail = new MailMessage("user@yahoo.com", "a.bbbb@company.org");
            SmtpClient client = new SmtpClient();

            client.Port = 25;
            client.DeliveryMethod = SmtpDeliveryMethod.Network;
            client.UseDefaultCredentials = false;
            client.Host = "smtp.gmail.com";

            mail.Subject = message.Subject;
            mail.Body = message.Message;

            client.Send(mail);
        }
    }

 

…no właśnie. Co jeśli dojdzie kolejny typ wiadomości do wysłania? Jak będzie wyglądać metoda SendMessage?

public void SendMessage(IMessage message)
        {
            if (message.Type == MessageType.EmailMessage)
            {
                MailMessage mail = new MailMessage("user@yahoo.com", "a.bbbb@company.org");
                SmtpClient client = new SmtpClient();
            
                client.Port = 25;
                client.DeliveryMethod = SmtpDeliveryMethod.Network;
                client.UseDefaultCredentials = false;
                client.Host = "smtp.gmail.com";
            
                mail.Subject = message.Subject;
                mail.Body = message.Message;
            
                client.Send(mail);
            }
            else if (message.Type == MessageType.SmsMessage)
            {
                //send sms
            }
        }

 

…no właśnie. Co jeśli pojawi się jeszcze jeden typ wiadomości do wysłania? Bez sensu, prawda? Takie rozwiązanie, na dłuższą metę będzie wątpliwe, a kod będzie coraz „trudniej utrzymywalny”.

Taki kod, lepiej wysłać nielubianemu koledze, niech on zrobi commit, niech on zostawi ślad w repo 😉 .

Ktoś mógłby powiedzieć, że można przecież wydzielić funkcjonalność wysyłania wiadomości dla poszczególnego typu, do osobnych metod. Cóż, wtedy nadal będziemy modyfikować klasę MessageSender, a przecież właśnie o to chodzi, że kod ma być otwarty na rozszerzenia, a zamknięty na modyfikacje!

Zgodnie z regułą cyklu „Nie SOLID-nie„, nie pokażę poprawnego kodu. Podpowiem tylko, że wystarczy utworzyć dwie klasy implementujące typ IMessage. Natomiast sam IMessage  będzie dostarczać metodę np. SendMessage. Klasa MessageSender może mieć swoją metodę Send(IMessage message) która będzie na przekazanym obiekcie message wywoływać metodę SendMessage.

Dobre rozwiązanie? Każda klasa implementująca IMessage sama sobie dostarcza sposób na wysłanie siebie. Nie potrzebujemy zmian/modyfikacji przy kolejnym typie wiadomości. Wystarczy utworzyć odpowiednią klasę i zaimplementować IMessage.

 

Grunt to być samodzielnym!

 

Reasumując

Trzymanie się zasady OCP powoduje, że kod poszczególnych „elementów” jest mniej powiązany i zależny od siebie wzajemnie (Loose Coupling). Dodatkowo, sprzyja pierwszej zasadzie SOLID, czyli Single Responsibility Principle. O ile nie zalecam kurczowego trzymania się zasady SRP, o tyle w przypadku OCP, dobrze jest się zatrzymać i przemyśleć, czy na pewno nie zbaczamy ze ścieżki OCP!

Proponuję również przyjrzeć się wzorcom architektonicznym, a w kontekście OCP wzorcowi Strategii.

 

Napisz komentarz! Dodaj coś od siebie!

Czołem!

 



About the author

Add comment

By Patryk

Autor serwisu

Patryk

Społecznościowe

Instagram

Newsletter



Historycznie

Tagi