SOLID - Zasada pojedynczej odpowiedzialności
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:
S – Zasada pojedynczej odpowiedzialności (Single Responsibility Principle – SRP)
O – Zasada otwarte-zamknięte (Open-Close Principle – OCP)
L – Zasada podstawiania Liskov (Liskov Substitution Principle – LSP)
I – Zasada segregacji interfejsu (Interface Segregation Principle – ISP)
D – Zasada odwrócenia zależności (Dependency Inversion Principle – DIP)
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.
[…] S – Zasada pojedynczej odpowiedzialności (Single Responsibility Principle – SRP) […]