docs icon indicating copy to clipboard operation
docs copied to clipboard

Приватные свойства - зачем?

Open Gerych1984 opened this issue 3 years ago • 4 comments

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

Итак имеем:

  1. Виджет табов, у которого все свойства приватны и имееют type hint
  2. Сеттер на каждое свойство (зачем там устанавливается через clone мне тоже непонятно, но опустим)
  3. В конструкторе виджета генерируется $options['id'] если не установлен

Мой "живой" случай в идеале, но не как сейчас:

$tabs = Tabs::widget();
//Ставим остальные свойства через сеттер

$this->registerJs('Vue.createApp(SourceTabsOptions).mount("#' . $tabs->options['id'] . '");');

Т.е. мне всё-равно какой id сгенерится виджетом, у меня к нему не привязано никаких CSS, ни чего другого. Но сейчас я вынужден каждый раз выдумывать этот самый id элемента, т.к. не могу получить приватный $options

Вопрос - а почему эти свойства не сделать публичными?

  1. Из-за type hint'ов я не смогу поставить недопустимое значение
  2. Это избавит от написания кучи однообразных сеттеров, которые по сути делают тоже самое
  3. При наличие того-же сеттера, приватные свойства не имеют смысла - т.к. я в любой момент могу его изменить через него.

При этом, если допустить ошибку и забыть при конфигурации указать "()" в конце, то yii3 заботливо предлагает добавить "$" в начало, чтобы установить свойство - что опять-же не работает с приватными свойствами. Но как минимум я так полагаю, что задумка такая была, но сейчас я мало где вижу ей применение, т.к. практически всё либо private, либо в лучшем случае protected

Заранее благодарен

Gerych1984 avatar Sep 20 '21 08:09 Gerych1984

For get id we can make method getId() public.

Private properties and getter/setters allow easier to make changes in the future, create readonly or writeonly properties, also in most cases getter or setter perform additional actions (for example, in Tabs setters make clone of widget).

Clone are needed in order for the widgets to be immutable.

vjik avatar Sep 20 '21 21:09 vjik

For get id we can make method getId() public.

Private properties and getter/setters allow easier to make changes in the future, create readonly or writeonly properties, also in most cases getter or setter perform additional actions (for example, in Tabs setters make clone of widget).

Clone are needed in order for the widgets to be immutable.

Делать getId() пабликом бессмысленно - т.к. на каждый вызов он будет генерить новый id за счёт накручивающегося счётчика + у данных виджетов "по хардкору" вписан суффикс (-tabs, -alert и т.д.) который может быть изменён в следующих релизах или вообще исчезнуть.

И перефразирую - readonly свойства нужны, не спорю. НО сейчас получается нет никаких read свойств, никаких геттеров - по сути мы имеем сплошное writeonly, т.е. мы можем установить значение, но не можем обратно получить. А это зачастую нужно и именно после манипуляций с этим свойством самим виджетом.

Ну и ИМХО - иммутабельность иммутабельностью, но может не стоит возводить её в абсолют, особенно там где она не "делает погоды"? Т.е. вот тут я не вижу от этого пользы, т.к. всё что требуется - это отрисовать нужный мне контент, в нужном мне месте в зависимости от виджета, всё. Но вижу вред - вынужден ждать когда будут потрачены человекочасы на написание геттеров к каждому свойству у которого есть сеттер и не факт, что они вообще будут написаны (хотя хватило бы просто сделать часть свойств, которые может установить пользователь публичными)

Т.е. к примеру я в миграциях повсеместно напрямую использую ColumnSchemaBuilder, чтобы дополнить недостающие в MigrationBuilder нативные pgsql типы (point, *range, uuid) и никаких проблем с отсутствием в нём иммутабельности я не обнаружил

Gerych1984 avatar Sep 21 '21 08:09 Gerych1984

In getId() id generated once (see code) and saved in private property.


If getters real need (has use cases), then we should added their.


In modern IDEs create base setters/getter very simple. For example, in PhpStorm: image


Immutable objects making impossible to make certain types of mistakes. When we pass an object to somewhere, we are sure that it will not change.

vjik avatar Sep 21 '21 13:09 vjik

Виджет табов, у которого все свойства приватны и имееют type hint

что удивительного в доступе к свойствам через сеттер/геттер?

Сеттер на каждое свойство (зачем там устанавливается через clone мне тоже непонятно, но опустим)

почитай о immutable objects

При наличие того-же сеттера, приватные свойства не имеют смысла - т.к. я в любой момент могу его изменить через него.

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

Для понимания подобных концепций стоит вначале ознакомится с SOLID

WinterSilence avatar Jan 14 '22 20:01 WinterSilence