All streams
Search
Write a publication
Pull to refresh
-2
0

Пользователь

Send message
Иногда AR, иногда хеши, зависит от того, что с этими данными нужно будет делать. Иногда делаю отдельный объект, в конструктор которого передается результат запроса в виде хешей, методы которого извлекают из такого результата нужную информацию.
Я для себя решил проблему отказавшись от маппинга как от основы. Мои объекты напрямую не отражают структуру БД, а просто генерируют запросы через инкапсулированный объект подключения к БД (бывает, пишу SQL, бывает использую query builder). Какой объект какие запросы будет генерировать — это уже вопрос распределения обязанностей. Иногда оказывается удобным использовать ActiveRecord, так как часто встречаются задачи работы с отдельными строками БД. Воспринимаю AR как объект для генерации запросов к отдельно взятой строке (кортежу) или строке и зависимым строкам (из связанных таблиц), не более.
В свое время сильно помогли идеи, изложенные здесь, но будьте осторожны, там все немного радикально, куча интерфейсов, надо подходить чуть менее категорично.
ООП не налагает ограничений на принципы, по которым можно выделять классы. Это просто способ структурирования кода программы. Если в предметной области есть понятие «Клиент» или «Заказ» и пр., то в программе совсем необязательно делать классы Customer и Order (и какие-либо другие абстракции, основанные прямо основанные на этих понятиях). Можно оперировать строками и таблицами через объект Connection или TableGatweay и пр., а бизнес-логику реализовать в службах/командах. В этом случае у нас также будет ООП, только принципы выделения абстракций, по которым построено приложение, будут другие. Может автор пытался сказать, что ему DDD не подошел, создание классов на основе сущностей предметной области это оттуда, а не из ООП. В ООП мы можем создавать классы, руководствуясь грубо говоря, чем угодно, что придумаем, что окажется удобным.
Обзор в первой части понравился. Про вариант 5 (eventual consistency) из первой части статьи: А под капотом у БД происходит не примерно то же самое? С помощью очереди фактически эмулируется журнал на уровне приложения, как мне видится. У БД все это может происходить только на одном сервере, а здесь можно распределить. Получилась система, в конечном счете обладающая транзакционностью, пусть и с фактическим READ_UNCOMMITED.
Про вторую часть: а разве идея с перекидываем подключения что-то даст по стравнению с моноллитным приложением? узкое место фактически остается — это одна БД, пусть и с премудростями по перекидыванию транзакций.
Инкапсулировать всю работу с БД за интерфесом, и не отражать доменные объекты(или таблицу) в коде?

Да.

Упращенно: Получение(внедрение) зависимостей через параметер в рантайме на основе типов.


А при чем тут тогда двойная диспетчеризация? Кто и что диспетчеризует? То что вы описали это просто передача зависимости в виде аргумента метода.

Программирование это компромиссы, не стоит идти в крайности и пытаться сокрыть вообще всё.


А я и не пытаюсь скрыть все. Я пытаюсь скрыть то, что нужно для упрощения использования объекта и улучшения уровня абстракции.

Гораздо лучше проектировать таких объектов менее связанными, стоит учитывать их жизненный цикл, который вообще то не зависит от DM/AR.


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

Именно, и как минимум реализация AR в Yii его нарушает.


И чем же? Тем что там все атрибуты public? Вы до конца мой комментарий дочитали? Я насчет синтаксического сахара уже сказал. В js вообще вон без этого живут.

Возмем простой RowDataGateway, если вы захотите внедрить зависимости к объекту реализующий RowDataGatewafInterface, то вам придеться при каждой загрузки такого объекта внедрить в него зависимостей.


А что в этом плохого?

Бизнес объекты не сложные, анемичные модели не приносят проблем.


Ну так вот она и суть современных практик по использованию доктрины и DataMapper. Сделать простые структуры данных с рудиментарной логикой и обложить процедурами в виде сервисов. Об этом и говорится в первом комментарии.

В общем это два противоположных похода к организации персистентности — инкапсуляция подключения к БД vs маппинг. Мне по душе больше первое, оно мне кажется ближе к ООП. Может вы думаете по-иному, предпочитаете маппинг. И в сообществе я думаю тоже будут противоположные точки зрения на этот вопрос. Я останусь при своем. Я думаю наша дискуссия затянулась, так что если хотите, можете привести свои контраргументы на этот пост и я предлагаю покончить с этим. Праздники заканчиваются).
Речь была про реализацию в Yii, или мы обсуждаем Row(Table)Gateway?


Речь про паттерн AR в общем, а не про какую-то конкретную реализацию.

Внедрение зависимостей через double dispatch, не нарушает инкапсуляцию.


1. Что понимаете под double dispatch? То что понимаю я, вообще тут не при чем.

2. Чтобы не было недопониманий, скажу что я понимаю под инкапсуляцией. Инкапсуляция это в первую очередь сокрытие какой-то функциональности и данных внутри объекта. Сокрытие информации, для того, чтобы вместо того, чтобы каждый раз возвращаться к чему-то конкретному, оперировать более общими/абстрактными понятиями/объектами. Модификаторы доступа public, private, protected это просто синтаксический сахар. Есть множество языков программирования, где можно работать используя объектную парадигму и в которых этого нет. Хотя бы тот же js. Да и в PHP если захотеть можно тоже что угодно получить через Reflection API. Тут все дело не в инструментах, а как с этим работает программист. Так вот, вместо того, чтобы сокрыть знание о сервисе, подключении к БД в объекте, вы предлагаете каждый раз передавать его используя внедрение метода, то есть вы скрываете меньше информации в своем объекте, чем могли бы, а это снижает уровень сокрытия информации, т.е. инкапсуляция становится более слабой.

В сущности не только структура, но и логика будет.


Нет, ну вы же сами написали, что сущности ближе к структурам. Вот это и имеется ввиду, когда говорят о том, что Doctrine это не ООП. А что логику поместить можно это понятно, только вот зависимости для ее работы придется всегда снаружи передавать, либо костылить с onLoad.
Как видите, это не ограничение со стороны doctrine, просто такая штука никому не нужна.
Причина в том, что сущности всё же ближе к структурам, чем к сервисам.

Так о том и речь. Само разделение на структуры и алгоритмы (на сущности/сервисы) ничего не напоминает?
Странное у вас определение инкапсуляции.

Я не приводил никаких определений. Что странного?

Например, есть юзер, хочу поменять пароль используя метод changePassword, но не хочу чтобы пароль был доступным для чтения, как мне это реализовать в AR?


А где в описании паттерна говорится, что поля AR всегда должны быть публичны? Здесь реализуемо и без public.
Сделать то можно, зная про инверсию зависимостей, вот пожалуйста, чисто для примера, код не протек в сервисы, снаружи будет только один вызов, как вы и хотели.


Нет, будет не так как я хотел. Будет еще код по получению объекта репозитория для передачи при вызове `increaseVolume`.
Это решение мне тоже не по душе, оно отражает то что я уже сказал. В Doctrine вынесли подключение к БД наружу, убрали его инкапсуляцию внутри объекта. Теперь чтобы делать подобные вещи, приходится это подключение всегда снаружи передавать, пусть и обернутое в репозиторий.
Вы говорите про использование ООП в качестве инструмента реализации модели домена. Но также можно модель домена реализовать с помощью PL/SQL и таблиц. Просто исторически так сложилось, что модели реализуют именно с помощью ООП. Модель в первую очередь делается в головах/на доске/бумаге и с помощью UML или других языков моделирования (ну или в специализированных программах), реализация должна быть близкой к модели, чтобы легче было понять где и что. Может иногда даже получится использовать код в качестве документации модели, код настолько понятен и прост (хотя я не видел такого, лучше уж фото рисунков на доске на телефон). Так вот тут и кроется основная цель DDD — получение реализации, облегчающей понимание модели и внесение изменений. Ни о какой изоляции от БД речи изначально не шло, это возникло как следствие желания упрощения реализации модели.
Соглашусь с Вами и добавлю от себя. В Doctrine в основу положено сознательное нарушение инкапсуляции. А это один из основополагающих принципов ООП. Вместо изоляции обращений к БД в классах AR, подключение к БД вынесено наружу. Сделано это ради того, чтобы код было легче читать и тестировать, переносить код на другие БД.
Как я уже сказал в комментариях, с базой AR нормально тестится, ничего страшного там нет. Лично мне наличие обращений к БД читать код не мешает. Перенос на другую БД? Бывает крайне редко и все равно потребуется большой рефаторинг. В общем с этим дело вкуса.
Но есть еще одно большое НО. Имея инкапсулированное подключение мы можем управлять транзакциями и блокировками изнутри AR, соответственно внутри сущностей Doctrine мы этого делать не можем. Например:

class Product extends ActiveRecord
{

     public function increaseVolume()
     {
          $this->db->transactional(function() {
              //это для блокировки, для того, чтобы другие процессы не перетерли счетчик, пока мы его не подифицируем
              $this->db->query('SELECT id FROM table WHERE id=:id FOR UPDATE', [':id' => $this->id])->scalar();
              $this->refresh();
              $this->volume = volume + self::VOLUME_STEP;
              $this->save();
          });
     }
}


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

AR нормально тестится вместе с БД, ну пусть чуть медленее. В чем тут проблема?
— Стараемся Делать контроллеры тонкими, максимально сократить код в экшенах и размазать по моделям и сервисам
4. Фикстуры не используются
По тестированию — встроеный codeception для юнитов и Newman для функциональных.

А как модели тестируете без фикстур тогда?
Из-за того, что в MySQL репликация асинхронная слейвы могли отставать на неопределенное время. Все критичные данные приходилось читать с мастера.
Из предыдущего пункта вытекает сложность разработки. Разработчик не мог просто сделать запрос к БД, а был обязан продумать готов ли он в каждом конкретном случае к отставанию слейва и если нет, то читать данные с мастера.


Пожалуйста, объясните, как при использовании асинхронной репликации (пусть и с плюшками) устраняются эти проблемы (что надо думать, откуда читаешь), за счет чего? Я с Percona Cluster не работал, но там репликация все равно асинхронная, и в любой момент времени отсутствие отставания, несоответствия читаемых данных (пусть даже на одну транзакцию) ничем не гарантировано. В приложении все равно надо думать о том, откуда именно читаешь, и для чего эти прочитанное будет использоваться — если для модификации — почти всегда надо читать с мастера, ограничение на отставание слейвов тут не сильно поможет, как мне кажется. Я думал что Percona, что Galera кластеры предназначены в первую очередь для защиты от потери транзакций в случае выхода мастера из строя, они не решают задачу масштабирования.
Смысл такой же, как и у других облачных ресурсов. Интересен, конечно же, для бизнеса.
MySQL очень бы пригодился. Может они со временем добавят. MySQL сейчас хорошо развивается.

Из всего что представлено мне больше всего интересны Managed Databases и Compute Cloud. Будет хорошо, если ресурсы на этих двух сервисах можно будет объединить в одну сеть Virtual Private Cloud.

А есть ли аналоги Managed Databases в России (желательно с MySQL, MongoDB, Redis)?
На мой взгляд диаграммы взаимодейтсвия надо использовать в первую очередь, т.к. они самые полезные.
Информационным Экспертом и пользуюсь, в связке с Low Coupling и High Cohesion. Для меня проще оказалось. Вообще мне Ларман нравится, хороший автор, по его книге GRASP и изучил.

Object design, roles responsibilities and collaborations. Автор Ребекка Вилфс-Брок? Читал эту фундаментальную книгу. 1990 год — фактически время первого прихода ООП к популярности. По-моему в ней на примерах (графический редактор и ATM) объясняется как вообще пользоваться ООП, что это такое и как проектировать объекты (метод последовательного приближения с помощью CRC-карт), про SOLID еще никто тогда не слышал (он не был сформулирован), и у г-жи Вилфс-Брок в чести множественное наследование. Не сказал бы, что эта методология сложна, она годная, но теперь есть UML, паттерны и принципы, все таки много с тех пор прошло времени.
Рад, что я не один так думаю). SRP как-то нечетко сформулирован. Вот статья по неясность SRP.

А вот что пишет про SRP Егор Бугаенко.
Если Вам виджеты нравится, Вам надо VueJs попробовать вместе с его однофайловыми .vue компонентами. Хороших результатов и высокой реюзабельности можно добиться.
Похоже тот, кто описываемый проект делал, вообще о порядке и поддержке не думал, просто скорее бы решить задачу. Конечно, в геттерах не надо что-то менять/сохранять.

Information

Rating
Does not participate
Location
Хабаровск, Хабаровский край, Россия
Registered
Activity