1. SPR (Single responsibility principle) - Принцип единственной обязанности

В объектно-ориентированном программировании принцип единственной обязанности (англ. Single responsibility principle) обозначает, что каждый объект должен иметь одну обязанность и эта обязанность должна быть полностью инкапсулирована в класс. Все его сервисы должны быть направлены исключительно на обеспечение этой обязанности.

Термин был введён Робертом С. Мартином в одноименной статье как часть его Принципов объектно-ориентированного проектирования, ставших популярными благодаря его книге Быстрая разработка программ. Принципы, примеры, практика. Мартин описал её как основанную на принципе связности, сформулированном Томом ДеМарко в его книге Structured Analysis and Systems Specification.

Мартин определяет обязанность как причину изменения и заключает, что класс или модуль должны иметь одну и только одну причину измениться. Объединение двух сущностей, изменяющихся по разным причинам и в разное время, считается плохим проектным решением.

Причина, почему нужно сохранять направленность класса на единственную цель в том, что это делает класс более здоровым.

Например, у нас есть несколько фигур и мы хотели бы суммировать все площади. Ну это довольно просто не так ли?

class Circle {
     public $radius;
 
     public function __construct($radius) {
         $this->radius = $radius;
     }
}
 
class Square {
     public $length;
 
     public function __construct($length) {
         $this->length = $length;
     }
}

Во-первых, мы создаем классы для наших фигур и в конструкторах устанавливаем нужные параметры. Затем мы создаем класс AreaCalculator и описываем в нем логику суммирования площадей фигур.

class AreaCalculator {
 
     protected $shapes;
 
     public function __construct($shapes = array()) {
         $this->shapes = $shapes;
     }
 
     public function sum() {
         // logic to sum the areas
     }
 
     public function output() {
         return implode('', array(
         "<h1>",
         "Sum of the areas of provided shapes: ",
         $this->sum(),
         "</h1>"
         ));
     }
}

Для использования класса AreaCalculator мы создаем простой объект, передаем в него массив с фигурами и выводим результат вычислений.

$shapes = array(
     new Circle(2),
     new Square(5),
     new Square(6)
);
 
$areas = new AreaCalculator($shapes);
 
echo $areas->output();

Проблема с методом вывода в том, что класс AreaCalculator реализует всю логику вывода в нем. Но что будет, если пользователь захочет вывести данные в формате JSON?

Вся логика по рассчету и выводу хранится в одном классе - это то, с чем борется принцип SPR. Класс AreaCalculator должен отвечать за вычисления суммы площадей (о чем говорит название класса), но не за вывод результатов в формате HTML.

Чтобы в полной мере реализовать принцип, нам нужно создать другой класс SumCalculatorOutputter, который будет заниматься выводом результатов.

Класс SumCalculatorOutputter будет работать следующим образом:

$shapes = array(
     new Circle(2),
     new Square(5),
     new Square(6)
);
 
$areas = new AreaCalculator($shapes);
$output = new SumCalculatorOutputter($areas);
 
echo $output->JSON();
echo $output->HAML();
echo $output->HTML();
echo $output->JADE();

Теперь вся логика по выводу информации пользователю представлена в классе SumCalculatorOutputter.

Принцип единственной обязанности используется в методологиях проектирования «от обязанности», таких как RDD и URDAD

Теги: Solid, Srp, Single responsibility principle, Принцип единственной обязанности


Похожие статьи

5. DIP (Dependency inversion principle) - Принцип инверсии зависимостей

4. ISP (Interface segregation principle) - Принцип разделения интерфейса

3. LSP (Liskov substitution principle) - Принцип подстановки Барбары Лисков

2. OCP (Open/closed principle) - Принцип открытости/закрытости