классическая связь почти для любого проекта.
User, который связан с UserProfile, UserPreferences, UserACL. Всем этим так или иначе надо управлять. и это идёт из требований.
И не надо мне про книги типа совершенный код, паттерны проектирования и прочую теорию которая НА ПРАКТИКЕ работает не далее написания ТЗ.
мы с вами наверное совершенно на разных проектах работаем, потому что у нас теория вписывается в практику. понятно, что есть неидеальные моменты, но все эти книги как раз таки написаны, основываясь на практике.
Вы видимо сами не разобрались как у вас класс работает, у вас на каждый вызов конструктора вызывается init() и в нем getMetadata(), которая не кешируется нигде.
Поправьте если не прав.
Могут, но если проект долгий, вы почувствуете разницу в сложности управления связей руками и на уровне ORM
А касательно кеширования и ленивой загрузки — во всех проектах для быстродействия мы делали это. Неважно с или без ORM
как я писал выше — абсолютно ничего. Потому и ADODB.
Так дело в том, что это наоборот не очень. Я глядя на код где устанавливается поле и потом сущность сохраняет ожидаю, что оно будет сохранено. Потому что не указано какие поля виртуальные, а какие реальные в БД.
Да и тянуть целую библиотеку ради возможности из массива сделать UPDATE/INSERT запрос тоже не вижу смысла, это пишется очень просто.
а нафига? проект с больше чем одной БД? Давайте оставим экзотику в стороне.
не такая уж и экзотика.
как вы тогда справляетсь с разными конфигурациями БД на живом, тестовм и локальном сервере?
тестирование зависит от проекта в котором данное решение используется. не вижу какой то специфики.
валидация сущности в beforeSave, он protected. Я хочу протестировать валидацию. Как мне это сделать без БД?
Я к тому, что класс жёстко завязан на БД и нельзя мокнуть её, а мокать БД в тестах — первое дело
косяк несущественный но спасибо.
https://gist.github.com/leon-mbs/7fb0a0881253a583017dadcdd8179325#file-entity-php-L96
а ещё вместо таких конструкций проще вызвать метод сразу со static::
зачем использовать ADODB, если есть PDO?
Из минусов:
Нельзя конфигурировать конекшен к базе: для разных Entity — разные конекшены (если переопределить getConnect, то конекшен переопределиться для всех классов)
Использование магических __get, __set (что если я присвою значение несуществующему в БД полю и вызову save() ?)
Быстродействие (парсить мтаданные для каждой сущности одного класса не кажется быстрым)
По самому коду очень много вопросов, например https://gist.github.com/leon-mbs/7fb0a0881253a583017dadcdd8179325#file-entity-php-L274 а потом вы возвращаете false
Что-то мне подсказывает, что если бы вы переопределили метод attributesToArray в Ваших тяжелых моделях, так, чтобы он возвращал действильно нужные вам поля, проблема бы исчезла
ну гибкость заключается в том, что вы можете добавлять/удалять слушателей без изменения кода с бизнес-логикой.
а по поводу изменения уровня логирования, то преимущество, что вы изменяете слушателя, который занимается логированием, а не класс с бизнес-логикой.
да и по правде говоря, бизнес-логика в сервисе, на мой взгляд, находиться на другом уровне абстракции нежели логирование.
реальный кейс — так сложилось, что на одном из проектов у нас был свой реализованный PSR-3 логгер. он был очень простой, писал в syslog и никак в общем-то не конфигурировался.
и тут появилась необходимость логгировать критические ошибки для некоторых модулей напрямую в Slack канал.
всё, что мы сделали — добавили в необходимые слушатели вызовы PSR-3 совместимого логгера в Slack.
как вы бы решали конкретно такую проблему, если бы вызывали напрямую логгер в сервисе с бизнес-логикой?
нет, дело как раз в добавлении дополнительной логики логирования. или к примеру для конкретного лог-сообщения вам нужно поменять уровень с debug на warning.
я клонил к тому, что для изменения логики логирования в таком случае вам придётся лезть в класс с вашей бизнес-логикой.
а это свидетельствует о нарушении принципа единой ответсвенности, а к чему это ведёт я думаю вы знаете.
ок, а если у вас такой случай.
при выполнении метода вашего сервиса, вы логируете что-то в 3 местах. и тут так вышло, что 1 из 3 вызовов вам надо писать не только в основное хранилище логов (файлы допустим), а ещё например отправлять письмом.
в вашем случаем вам придётся лезть в код вашего сервиса и добавлять этот код, верно?
Строго говоря, класс, который занимается шифрованием, про файлы сильно знать не должен. Более «чистый» пример бы был про какие-нибудь Reader'ы — буфера, файлов, потока и тд
Ну а по самому паттерну, точнее реализации все отлично, спасибо :)
тяжело сказать, хорошую ли идею двигает автор, так как с первого прочтения въехал не до конца, буду перечитывать.
но по тому, во что въехал
1) главный императив — борьба со сложностью, пока мне кажется решение излишне сложным
2) ок, что делать с сайд эффектами? во фронтенде их уйма, да и к тому же многое асинхронно
User, который связан с UserProfile, UserPreferences, UserACL. Всем этим так или иначе надо управлять. и это идёт из требований.
мы с вами наверное совершенно на разных проектах работаем, потому что у нас теория вписывается в практику. понятно, что есть неидеальные моменты, но все эти книги как раз таки написаны, основываясь на практике.
Поправьте если не прав.
А касательно кеширования и ленивой загрузки — во всех проектах для быстродействия мы делали это. Неважно с или без ORM
Так дело в том, что это наоборот не очень. Я глядя на код где устанавливается поле и потом сущность сохраняет ожидаю, что оно будет сохранено. Потому что не указано какие поля виртуальные, а какие реальные в БД.
Да и тянуть целую библиотеку ради возможности из массива сделать UPDATE/INSERT запрос тоже не вижу смысла, это пишется очень просто.
не такая уж и экзотика.
как вы тогда справляетсь с разными конфигурациями БД на живом, тестовм и локальном сервере?
валидация сущности в beforeSave, он protected. Я хочу протестировать валидацию. Как мне это сделать без БД?
Я к тому, что класс жёстко завязан на БД и нельзя мокнуть её, а мокать БД в тестах — первое дело
https://gist.github.com/leon-mbs/7fb0a0881253a583017dadcdd8179325#file-entity-php-L96
а ещё вместо таких конструкций проще вызвать метод сразу со static::
недавно столкнулся с проблемой выбора слоя для работы с БД для приложения построенного на основе ReactPHP
Из минусов:
И пару вопросов:
оставлю тут ссылочку
и далее вы приводите картинку со структурой папок проекта.
структура директорий не равно архитектура приложения.
а по поводу изменения уровня логирования, то преимущество, что вы изменяете слушателя, который занимается логированием, а не класс с бизнес-логикой.
да и по правде говоря, бизнес-логика в сервисе, на мой взгляд, находиться на другом уровне абстракции нежели логирование.
реальный кейс — так сложилось, что на одном из проектов у нас был свой реализованный PSR-3 логгер. он был очень простой, писал в syslog и никак в общем-то не конфигурировался.
и тут появилась необходимость логгировать критические ошибки для некоторых модулей напрямую в Slack канал.
всё, что мы сделали — добавили в необходимые слушатели вызовы PSR-3 совместимого логгера в Slack.
как вы бы решали конкретно такую проблему, если бы вызывали напрямую логгер в сервисе с бизнес-логикой?
я клонил к тому, что для изменения логики логирования в таком случае вам придётся лезть в класс с вашей бизнес-логикой.
а это свидетельствует о нарушении принципа единой ответсвенности, а к чему это ведёт я думаю вы знаете.
а решение, которое вам предложил VolCh основано на вот таком принципе/поведении http://symfony.com/doc/current/components/event_dispatcher/introduction.html
это гораздо более гибкий вариант поведения
при выполнении метода вашего сервиса, вы логируете что-то в 3 местах. и тут так вышло, что 1 из 3 вызовов вам надо писать не только в основное хранилище логов (файлы допустим), а ещё например отправлять письмом.
в вашем случаем вам придётся лезть в код вашего сервиса и добавлять этот код, верно?
Вы бы дополнили статью информацией о том, как правильно работать с моками, как переиспользовать например поведение, сложные случаи и тд
Ну а по самому паттерну, точнее реализации все отлично, спасибо :)
но по тому, во что въехал
1) главный императив — борьба со сложностью, пока мне кажется решение излишне сложным
2) ок, что делать с сайд эффектами? во фронтенде их уйма, да и к тому же многое асинхронно