Расширение класса внешними методами и переменными

Yoskaldyr

"Спамер"
Партнер клуба
@fixxxer а там не нужны сильно понимающие архитектуру, нужны те кто умеет делать по подобию готового кода (есть такие примеры, делай подобно) и прикрутить готовую верстку в шаблон. Т.е. самые нудные и унылые задачи. Постоянная команда никуда не собирается уходить. Смысла в большем количестве хороших php разработчиков сейчас нет, хоть неслабый такой басфактор и присутствует. Но такое везде в мелком и среднем бизнесе. Все-таки бизнес не уровня мегакорпорации или крупного бодишопа, а довольно таки средний.
 

Yoskaldyr

"Спамер"
Партнер клуба
Всетаки топик сильно ушел от темы... Ну как всегда в общем :)
 

WMix

герр M:)ller
Партнер клуба
Идея держать коллекцию мутабельных обьектов, довольна обычна с точки зрения команды, не понятно зачем читабельные свойства обьекта. Те либо крестик, либо трусики
 

Yoskaldyr

"Спамер"
Партнер клуба
@WMix потому что это данные, к которым нужен доступ извне, а не только изнутри объекта.
И структурированный доступ к данным это первоначальная и основная задача этого объекта.
Вторая задача согласованно мутировать объект, чтобы он оставался валидным.
И самая минимальная задача - вычисляемые свойства, совсем не много.
В плане использования извне чтение свойств это >99% всех операций. И только совсем немного мутирования.
Данные объединены с поведением - классическое ООП. И пока никто здесь не доказал обратного.
Насчет полной иммутабельности - единственная проблема в данном конкретном случае - размер этих объектов и необходимость работать со связными списками (не сильно большими, но все же)

Это ни плохая архитектура, ни что-то другое. Это осознанный компромисс для таких здоровых датаориентированных объектов.

И изначально разговор был не о больших объектах, не о плюсах и минусах мутабельности и иммутабельности, а о writeonce rfc (которое вообще-то идиотское).

Всего-то хотелось полезную фичу сишарпа (и некоторых других языков), чтобы запрещать модификации извне, но оставлять возможность чтения на уровне конструкций языка, не с помощью костылей. И это была просто хотелка, как защита от дурака. С костылями и сейчас все можно сделать и даже без черной магии типа ffi (паблик свойство которое в конструкторе делается unset и дальше вся работа с ридонли полями через приватный массив данных через __get и запрет на __set)
 

fixxxer

К.О.
Партнер клуба
Если совсем немного мутирование до чтения, тогда не вижу проблем с тем, чтобы посчитать и вернуть чистый value object.
А если вперемешку, то где-то проблемы с размытием ответственностей.
 

Yoskaldyr

"Спамер"
Партнер клуба
@fixxxer А что делать с ООП - данные должны быть вместе с поведением. Т.к. тут именно объект с данными и именно поведение этого объекта. Вот вообще 100% классическое ООП. Конечно можно вынести все поведение в отдельный мутатор класс, но вот тогда и будет как раз классическое нарушение ОПП. И кстати именно так раньше и было, отдельный мутатор класс, правда работал с массивом
 

fixxxer

К.О.
Партнер клуба
Я про то, что когда у тебя паблики, часть поведения неминуемо просочится наружу.
 

whirlwind

TDD infected, paranoid
А immutable тут необходим для решения проблемы параллельного доступа или по каким-то другим причинам?
 

Yoskaldyr

"Спамер"
Партнер клуба
@whirlwind Мне не нужен immutable, мне нужен запрет записи для паблик свойств извне класса.
Когда я писал это
тупо бы перенесли из c# public int MyInt{ get; private set; } + readonly....
я говорил о rfc а не о моей ситуации.

В моем случае как раз удобно сишарповское c# public int MyInt{ get; private set; } А readonly, т.е. иммутабельость не сильно подходит. Просто все начали доказывать что именно иммутабельность нужна в моем случае, хотя я этого не говорил.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
И здесь нет вообще никакого нарушения SOLID или еще чего умного что здесь на форуме любят сначала додумать, а потом приплести в обсуждение. Классическое ООП - просто данные вместе с их поведением (в конкретном случае изменение внутреннего стейта).
Есть нарушение буквы D - инверсии зависимостей, потому что
это полностью публичные данные - контракт объекта.
а с публичными свойствами нет абстракции, вызывающий код "верхнего уровня" прямо зависит от свойств "нижнего уровня".
По определению слова "свойство" оно не может быть абстракцией. Контракт - это что отдаем, что получаем в ответ.
Контракт, он же абстракция, в php объявляется интерфейсом, и свойства не включает специально.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Мне не нужен immutable, мне нужен запрет записи для паблик свойств извне класса.
я говорил о rfc а не о моей ситуации.

В моем случае как раз удобно сишарповское c# public int MyInt{ get; private set; } А readonly, т.е. иммутабельость не сильно подходит. Просто все начали доказывать что именно иммутабельность нужна в моем случае, хотя я этого не говорил.
никто не пропустит подобный rfc, это отработали в Java когда мы пешком под стол ходили, а C# просто залили сахарным сиропом для привлечения индусов
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
А нет такого, ты придумал это словосочетание. Есть DTO и VO, по сути одно и то же, и в них ... не очень нужна иммутабельность.

100500 полей это свойства объекта физического мира (метрики статистики юзера). Если брать персистенс слой, то в таблице больше 10К колонок (абсолютно равнозначные decimal значения) по которым может считаться очень хитровые...ая групповая стата.
С точки зрения логики взаимодействия полей, одни поля влияют на другие, так что вся логика изменения, сравнения между объектами зависит только от этих самих данных.
это называется Active Record :)

к самому объекту это не имеет отношения, он вообще ничего не знает о персистенс слое.
или он знает имена полей и имеет к нему отношение, или получает от слоя базы структуру с данными без логики зависимостей между полями ( в структуре может быть много уровней вложенности объектов )
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Ну учитывая что в таком случае будет только 2-й перерасход памяти и полностью прогнозируемый.
не будет, в том числе с clone
PHP:
class A {
    private $foo;
    public function __construct()
    {
        $this->foo = str_repeat('0000000000', 1000000);
    }
    public function export()
    {
       $export = new class{public $foo;};
       $export->foo = $this->foo;
       return $export;
    }
}
echo memory_get_usage(), "\n";
$a = new A;
echo memory_get_usage(), "\n";
$b = clone $a;
echo memory_get_usage(), "\n";
$dto = $b->export();
echo memory_get_usage(), "\n";
422328 - до str_repeat
10425016 - для str_repeat выделили память
10425112 - после clone выделения памяти не было
10426192 - при export() выделения памяти тоже нет

можно спокойно клонировать, экспортировать DTO, и не рассказывать сказки про память
Главный плюс мутабельности, в данном случае, что нельзя случайно сделать дубликат объекта. Это проблема как раз редких ошибок, которые вылезут на реальных данных а не в тестах (ну или тесты делать на реальных данных)
случайно создать объект невозможно
 

fixxxer

К.О.
Партнер клуба
А нет такого, ты придумал это словосочетание. Есть DTO и VO, по сути одно и то же, и в них ... не очень нужна иммутабельность.
Не то, чтобы прямо нужна (жить без нее можно). Но удобно.
Никогда не встречался с косяками, когда случайно мутируется DateTime или Carbon? Хотели посчитать "время через месяц", а получили заодно мутацию объекта.
Очень больно такое ловить.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
не встречался
удобно, но важность этой фичи относительно других я считаю меньшей
 

fixxxer

К.О.
Партнер клуба
Проблема тут в том, что мутация как нежелательный сайд-эффект далеко не всегда ловится тестами и может оставаться незамеченной, пока не появится code path, на котором оно проявляется - а оно может появиться вообще через полгода.

Когда это банальный DTO, проблемы особо и нет. А когда это VO внутри сущностей, тогда все куда печальнее - "случайное" изменение может заперсиститься, и если нет полноценного евент-сорсинга, еще хрен поймешь, почему и как все вернуть. В общем, это не кажется особой проблемой, пока не наешься с этим дерьма :) Вон в Yii рекурсию в конструкторе тоже проблемой не считали. :)
 

AmdY

Пью пиво
Команда форума
Только вот эта проблема теоретическая, на практике за всю карьеру её один раз встречал. И то в javascript, и то на проекте, где во всю использовался ImmutableJs. А вот обслуживающего кода приходилось писать кучу, плюс потери по памяти и перфомансу.
 

whirlwind

TDD infected, paranoid
Вы все говорите об одном и том же. Если что либо нарушает SOLID, это надо запретить к чертям собачьим. Например, final противоречит Open/Close. А паблик проперти не полиморфны, а значит противоречат LSP. В шарпе вполне годное решение set/get. Просто сахарок для создания сеттера и геттера. И они полиморфны. Это не то же самое, что доп спецификатор на паблик проперти.

ЗЫ. И кстати насчет что там в Java что то давно отработали. Java>8 добавили наконец то var. Я сильно не уверен, что это пошло во вред. Смотреть пары парустрочных дефайнов, тип которых вообще в контексте не роляет, вот это реальная попаболь была.
 
Последнее редактирование:
Сверху