- Нарушение инкапсуляции: Инкапсуляция — это один из основных принципов ООП, предполагающий скрытие внутреннего состояния объекта и предоставление доступа к нему только через методы. Геттеры и сеттеры, предоставляя прямой доступ к полям объекта, нарушают этот принцип, делая состояние объекта слишком открытым.
- Привязка к реализации: Использование геттеров и сеттеров делает код зависимым от конкретной реализации объекта. Если внутреннее представление объекта изменится, это потребует изменений в коде, который использует эти геттеры и сеттеры.
- Отсутствие поведения: Объекты в ООП должны быть представлены через поведение (методы), а не через данные (поля). Геттеры и сеттеры делают акцент на данных, а не на поведении, что противоречит идеям ООП.
Что использовать вместо них?
- Методы, ориентированные на поведение: Вместо извлечения данных из объекта и выполнения действий с ними снаружи, лучше попросить объект выполнить необходимое действие самостоятельно. Это поддерживает инкапсуляцию и абстракцию, позволяя объекту контролировать свое состояние.
// Вместо использования геттера для получения данных и выполнения действия
int age = person.getAge();
if (age > 18) {
// действие
}
// Лучше добавить метод, который инкапсулирует проверку и действие
if (person.isAdult()) {
// действие
}
- Использование шаблонов проектирования: Некоторые шаблоны проектирования, такие как Стратегия или Команда, позволяют инкапсулировать поведение и изменять его во время выполнения программы, не раскрывая внутреннее состояние объекта.
- Иммутабельность: Где это возможно, делайте объекты неизменяемыми (immutable). Это означает, что состояние объекта устанавливается при создании и не может быть изменено. Это устраняет необходимость в сеттерах и делает программу более предсказуемой.
- Принцип "Tell, Don’t Ask": Вместо запроса состояния объекта для выполнения действия (Ask), объекту следует "сказать", чтобы он выполнил нужное действие (Tell). Это уменьшает связанность и повышает гибкость кода. Пример:
class Order {
private $status;
public function __construct() {
$this->status = 'pending';
}
public function needCheck() {
$this->status = 'needCheck';
}
public function complete() {
if ($this->status === 'needCheck') {
throw new Exception('Order cannot be completed, it needs to be checked');
}
$this->status = 'completed';
}
public function getStatus() {
return $this->status;
}
}
$order = new Order();
$order->needCheck();
try {
$order->complete();
} catch (Exception $e) {
echo $e->getMessage();
}
Вывод
Хотя в некоторых случаях использование геттеров и сеттеров может быть оправданным (например, при проектировании библиотек или фреймворков, требующих большой гибкости), в целом стараться минимизировать их использование и сосредоточиться на более высокоуровневых абстракциях и поведении объектов — хорошая практика в объектно-ориентированном программировании. Sources:
Leave a reply