SOLID

Jest to akronim skracający w jednym słowie pięć podstawowych zasad programowania obiektowego. Przestrzeganie ich pomaga w pisaniu czytelnego i łatwego w utrzymaniu kodu. Te zasady to:

W poniższym artykule skupię się na opisaniu zasady pojedynczej odpowiedzialności.

Definicja

Każda klasa powinna mieć tylko jedną odpowiedzialność i tylko jeden powód do zmiany. Jeżeli ma więcej niż jedną odpowiedzialność i staje sięzbyt skomplikowana, trudna do testowania i modyfikacji.

Może być także stosowana do pojedynczych funkcji, plików w kodzie źródłowym, bibliotek, modułów czy pakietów

Symptomy łamania

  • klasa ma zbyt wiele publicznych metod
  • zbyt skomplikowany kod
  • dodawanie nowych metod jest trudne
  • jedna klasa zawiera zbyt wiele funkcjonalności

Przykład złamania reguły SRP

Stworzyliśmy klasę Image, która ma za zadanie obsługiwać nam obraz. Zawiera wysokość i szerokość obrazu. Problem w tym, że w tej jednej klasie umieściliśmy 3 różne odpowiedzialności: przechowywanie danych o obrazie, rysowanie i zapisywanie obrazu do pliku. Te zadania nie są związane z celem klasy i mogą być powodem do jej zmiany.

public class Image {
    private int width;
    private int height;

    public Image(int width, int height) {
        this.width = width;
        this.height = height;
    }
    
    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public void drawPixel(int x, int y) {
        System.out.println("Rysuję pixel");
    }
    public void drawLine(int x1, int y1, int x2, int y2){
        System.out.println("Rysuję linię");
    }
    public void saveAsPng(String path){
        System.out.println("Zapisuję obraz w formacie PNG");
    }
    public void saveAsJpeg(String path){
        System.out.println("Zapisuję obraz w formacie JPEG");
    }
} 

Podzielmy zatem te klasy tak, aby każda z nich miała tylko jedną, jasno oddzieloną odpowiedzialność. Na przykład, można stworzyć klasy Canvas i ImageSaver, które będą się zajmowały odpowiednio rysowaniem  i zapisywaniem obrazu. Klasa Image będzie tylko przechowywać dane o obrazie i nie będzie mieć innych zadań. Oto przykład poprawionego kodu:

public class Image {
    private int width;
    private int height;

    public Image(int width, int height) {
        this.width = width;
        this.height = height;
    }
    
    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }
} 
public class Canvas {
    private Image image;

    public Canvas(Image image) {
        this.image = image;
    }

    public void drawPixel(int x, int y) {
        System.out.println("Rysuję pixel");
    }
    public void drawLine(int x1, int y1, int x2, int y2){
        System.out.println("Rysuję linię");
    }
} 
public class ImageSaver {
    Image image;

    public ImageSaver(Image image) {
        this.image = image;
    }

    public void saveAsPng(String path){
        System.out.println("Zapisuję obraz w formacie PNG");
    }
    public void saveAsJpeg(String path){
        System.out.println("Zapisuję obraz w formacie JPEG");
    }
} 

Teraz każda klasa ma tylko jedną odpowiedzialność i tylko jeden powód do zmiany. Kod jest bardziej czytelny, łatwiejszy do testowania i modyfikacji. Stosowanie się do zasady SRP pomaga w tworzeniu kodu o wysokiej jakości i niskim sprzężeniu.