@runprogr

Как правильно задавать свойства классам php?

Допустим в классе Test есть свойства
public $name;
public $subname;

Можно напрямую задать значения

$test = new Test;

$test->name = 'name';
$test->subname = 'subname';

Но заметил, что чаще всего в классе создают функции, например

public function setName($name) {

$this->name = $name;
}
И значение задается через метод

$test->setName('name');

Зачем это делается и как все таки поступать правильно ?
  • Вопрос задан
  • 203 просмотра
Решения вопроса 1
@EvgeniiR
https://github.com/EvgeniiR
Правильно - задавать свойства в конструкторе класса. А публичные поля или методы get/set это нарушение инкапсуляции.
Экземпляр класса должен полноценно работать и иметь в себе все необходимые для работы данные сразу после его создания.

Есть исключения когда мы имитирируем структуры данных через классы-DTO(В PHP нету встроенных типов структур/data-классов), но заполнение и там должно быть через конструктор.

Странно, здесь же на тостере Когда использовать static метода? например, пишут что правильная работа с ооп, это как раз задавать параметры через методы, а не через конструктор.

На Тостере много чего пишут, не стоит всему верить, точнее стоит ничему не верить, а анализировать :)
В плане каких-то конкретных терминов часто можно узнать очень много интересных вещей загуглив первоисточник термина/историю появления(в т.ч. причины).

Постарайтесь определить цели и понять как эти варианты помогают вам эти цели достичь. А "правильных" вариантов без заданной цели не может быть.
В будущем в этом плане стоит смотреть на концепты Coupling/Cohesion, и почему они важны(книжки Clean Architecture, Clean Code и т.п., так же принцип Low Coupling + High Cohesion входит в паттерны GRASP).

По теме - задавая параметры через set() методы мы:
- Подразумеваем что все пользователи нашего класса знают какие у него параметры, и более того - что они означают. Это создаёт большую нагрузку на пользователей класса, усложняет клиентский код.
- Позволяем в любом месте где используется класс поменять что-то внутри, и неожиданно обнаружить ошибки в других местах системы. А ещё настройки могут конфликтовать друг с другом, и одни свойства зависеть от других. Установка одного поля может требовать установки другово, и такие вещи стоит указывать на уровне интерфейса, то есть сделать вместо условных setStartDate() и setEndDate() метод setDatePeriod(DatePeriod period), даже если внутри класса это два поля.

Такие вещи желательно изолировать, и на уровне клиентского кода класса вызывать лишь методы которые делают то, что нам нужно. Думаю не сложно понять, что чем больше нужных нам вещей делает сторонний модуль, который мы вызываем, чем меньше нам нужно информации, чтобы вызвать у него нужные методы, и чем больше контроля над собственной валидностью мы перекладываем на него, тем проще нам пользоваться этим модулем.

И ещё - есть разница между методами которые меняют состояние класса, и конкретно "сеттерами". Семантика важна. То что внутри класса что-то меняется нас не интересует. Нам важно лишь чтобы выполнилось то, что мы ожидаем от класса. Если мы хотим обновить статью, мы вызовем метод updateArticle(), или какой-нибудь changeTitle(), например. Если мы хотим кофе мы скажем машинке makeEspresso(), а не будем указывать количество зёрен, упростив таким образом клиентский код.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы