Zasada Pojedynczej Odpowiedzialności



Definicja

Zasada pojedynczej odpowiedzialności (ang. Single Responsibility Principle, SRP) mówi, że każda klasa, moduł lub funkcja powinna mieć tylko jeden powód do zmiany. Innymi słowy – każda część kodu powinna zajmować się tylko jednym, jasno określonym zadaniem. Dzięki temu kod staje się prostszy, bardziej przejrzysty i łatwiejszy w utrzymaniu.

Przykład z życia

Wyobraźmy sobie fabrykę prefabrykatów żelbetowych, która produkuje belki i płyty.
Pracownik linii produkcyjnej ma dwa zadania:

  • kontrolować jakość elementów,
  • oraz przygotowywać raporty do działu sprzedaży.

W praktyce to nieefektywne — jeśli pracownik zajmuje się wszystkim, może popełnić błędy lub spowolnić proces. Lepiej, aby jedna osoba odpowiadała za kontrolę jakości, a inna za raportowanie.
To samo dotyczy kodu — klasa powinna mieć jedną odpowiedzialność, a nie próbować „robić wszystkiego naraz”.

Przykłady przed i po zastosowaniu zasady

PRZED

Przykład poniżej przedstawia klasę, która narusza zasadę SRP — zajmuje się zarówno obliczaniem masy prefabrykatu, jak i generowaniem raportu.

Klasa PrefabElement odpowiada zarówno za logikę obliczeniową, jak i za generowanie raportu.
Jeśli zmieni się sposób raportowania (np. raport ma być zapisywany do pliku CSV zamiast drukowany), trzeba będzie zmienić klasę, mimo że nie dotyczy to jej głównej funkcji (obliczeń).

public class PrefabElement {
    private double length;
    private double width;
    private double height;
    private double density;


    public PrefabElement(double length, double width, double height, double density) {
        this.length = length;
        this.width = width;
        this.height = height;
        this.density = density;
    }

    public double calculateWeight() {

        return length * width * height * density;
    }



    public void generateReport() {
        double weight = calculateWeight();
        String report = "Prefab element: " + length + "x" + width + "x" + height + " m\n"
                      + "Weight: " + weight + " kg\n"
                      + "Report generated for production control.";
        System.out.println(report);
    }

    public static void main(String[] args) {
        PrefabElement beam = new PrefabElement(6.0, 0.3, 0.5, 2500.0);
        beam.generateReport();
    }
}
Designed by Freepik

PO

Po wprowadzeniu zasady SRP rozdzielamy obowiązki na dwie klasy:

-PrefabElement – odpowiada tylko za dane i obliczenia,
-ReportGenerator – odpowiada za tworzenie raportów.

Teraz każda klasa ma jedną, jasno określoną odpowiedzialność:

-PrefabElement → obliczenia techniczne,
-ReportGenerator → prezentacja i raportowanie.

Jeśli w przyszłości zmienimy sposób generowania raportów (np. eksport do PDF), wystarczy zmodyfikować tylko ReportGenerator, a nie dotykać logiki obliczeń.

// Klasa odpowiedzialna tylko za dane i obliczenia techniczne
public class PrefabElement {
    private double length;
    private double width;
    private double height;
    private double density;

    public PrefabElement(double length, double width, double height, double density) {
        this.length = length;
        this.width = width;
        this.height = height;
        this.density = density;
    }

    public double calculateWeight() {
        return length * width * height * density;
    }
    public double getLength() {
        return length;
    }
    public double getWidth() {
        return width;
    }
    public double getHeight() {
        return height;
    }
}

// Klasa odpowiedzialna tylko za generowanie raportu
public class ReportGenerator {
    public void generate(PrefabElement element) {
        double weight = element.calculateWeight();
        String report = "Prefab element: " + element.getLength() + "x"
                      + element.getWidth() + "x" + element.getHeight() + " m\n"
                      + "Weight: " + weight + " kg\n"
                      + "Report generated for production control.";
        System.out.println(report);
    }
}

// Klasa główna – przykład użycia
public class Main {
    public static void main(String[] args) {
        PrefabElement beam = new PrefabElement(6.0, 0.3, 0.5, 2500.0);
        ReportGenerator reporter = new ReportGenerator();
        reporter.generate(beam);
    }
}