C#

SOLID - Zasada pojedynczej odpowiedzialności

Zasada pojedynczej odpowiedzialności jest pierwszą zasadą mnemoniku SOLID. SOLID jest to, krótko mówią zbiór pięciu założeń programowania obiektowego,  finalnie sformułowanych i opisanych przez Roberta C. Martina – wybitnego programistę. Warto zaznaczyć, że reguły, na których opiera się SOLID, zostały wypracowane przez developerów na przestrzeni lat, ale zostały spopularyzowane właśnie przez tego Pana.

SOLID

S – Zasada pojedynczej odpowiedzialności (Single Responsibility Principle – SRP)
OZasada otwarte – zamknięte – (Open-Closed Principle – OCP)
LZasada podstawiania Liskov  – (Liskov Substitution Principle – LSP)
I  – Zasada segregacji interfejsu – (Interface Segregation Principle – ISP)
D – Zasada odwracania zależności – (Dependency Inversion  Principle DIP)

Każdą z tych zasad będę przedstawiał w kolejnych częściach cyklu. W tej zajmiemy się pierwszą z nich, czyli zasadą pojedynczej odpowiedzialności. W myśl tej zasady klasa powinna mieć pojedynczą odpowiedzialność – jeden powód do zmiany.

Zasada pojedynczej odpowiedzialności

Spójrzmy na klasę przedstawioną poniżej:

class BadEmployee
{
    private readonly string _email;
    private readonly int _salary;
    private string _name;
    private string _surname;

    public BadEmployee (string name, string surname, string email, int salary)
    {
        _salary = salary;
        _email = email;
        _name = name;
        _surname = surname;
    }
}

Klasa ta opisuje pracownika. Zawiera imię, nazwisko, wiek oraz adres e-mail. Mając taką klasę, zapewne chcielibyśmy sprawdzać poprawność danych pracownika. Dodajmy zatem metody sprawdzające e-mail oraz to czy np. pracownik zarabia więcej niż 2500zł.

class BadEmployee
{
    private readonly string _email;
    private readonly int _salary;
    private readonly int _salaryThreshold = 2500;
    private string _name;
    private string _surname;

    public BadEmployee (string name, string surname, string email, int salary)
    {
        _salary = salary;
        _email = email;
        _name = name;
        _surname = surname;
    }

    private string ValidateEmail ()
    {
        string message = string.Empty;
        if (string.IsNullOrWhiteSpace (_email)) message += "brak emaila, ";
        if (!_email.Contains ("@")) message += "niepoprawny email, ";

        return message;
    }

    private bool CheckSalary ()
    {
        return _salary >= _salaryThreshold;
    }
}

W porządku! Mamy pracownika, potrafimy sprawdzić poprawność jego danych. Nie bez powodu nazwałem klasę BadEmployee, bo rzeczywiście jest to zły pracownik. Otwarcie łamie zasadę SRP, ponieważ klasa ta przechowuje dane pracownika oraz jest odpowiedzialna za sprawdzenie poprawności tych danych.

Czysty kod. Podręcznik dobrego programisty
W księgarni informatycznej Helion znajdziesz: Czysty kod. Podręcznik dobrego programisty , autor: Robert C. Martin, wydawnictwo: Helion. Produkt dostepny w formacie: Książka, ebook. Pobierz i przeczytaj darmowy fragment.
Czysty kod. Podręcznik dobrego programisty

Walidacja powinna zostać oddelegowana do innej klasy, przez co zasada SRP będzie działać, a odpowiedzialności zostaną jasno rozdzielone. Spójrzmy na kod poniżej:

class GoodEmployee
{
    private readonly string _email;
    private readonly int _salary;
    private readonly ValidityTool _validityTool;
    private string _name;
    private string _surname;
    public GoodEmployee (string name, string surname, string email, byte salary)
    {
        _salary = salary;
        _email = email;
        _name = name;
        _surname = surname;
        _validityTool = new ValidityTool ();
    }

    private string ValidateEmail ()
    {
        return _validityTool.ValidateEmail (_email);
    }

    private bool IsAdult ()
    {
        r
        eturn _validityTool.CheckSalary (_salary);
    }
}

class ValidityTool
{
    private readonly int _salaryThreshold = 2500;
    public string ValidateEmail (string email)
    {
        string message = string.Empty;
        if (string.IsNullOrWhiteSpace (email)) message += "brak emaila, ";
        if (!email.Contains ("@")) message += "niepoprawna email, ";
        return message;
    }

    public bool CheckSalary (int salary)
    {
        return salary >= _salaryThreshold;
    }
}

Dodaliśmy klasę ValidityTool,  która jest odpowiedzialna za sprawdzenie poprawności danych. W klasie dobrego pracownika oddelegowujemy zadanie walidacji do klasy ValidityTool.

Co zyskaliśmy? Podział odpowiedzialności – każda klasa ma swój jasno określony cel. Klasa GoodEmployee jest typowym przykładem klasy modelu. Tego typu klasy powinny tylko przechowywać dane, natomiast inne zadania (np. walidacja) powinny zostać oddelegowane do innych klas.

Na koniec

Należy pamiętać o tym, aby tworzone klasy miały jedno jasno określone zadanie. Mimo że jest to prawdopodobnie najłatwiejsza zasada w mnemoniku SOLID, to stosowanie jej jest stosunkowo trudne. Często trudno jest wywnioskować czy napisana klasa rzeczywiście posiada pojedynczą odpowiedzialność. Jednakże wraz ze zdobytym doświadczenie staje się to coraz łatwiejsze.

Tagi