Михаил: Должны, если в идеале как ValueObject и должны поддерживать eager и lazy loading. В таких штуках как Doctrine для класса предметной области создается Proxy, который перехватывает запрос (при lazy loading) к $user->addreses и направляет его в базу(или в другое место, это решает репозиторий) для последующей гидрации. Я бы 10 раз подумал перед тем как решить все это писать самому в YII. ActiveRecord в этом плане работает со связями по другому. Вы можете посмотреть какие методы используются для вытягивания моделей и подменить их, но я думаю что вы столкнетесь с невероятным количеством проблем. Проще будет вытягивать их из API по потребности(может быть даже по крону) и преобразовывать в Yiiшные модели. ActiveRecord сильно связывает вам руки в этом плане и загрязняет код.
Михаил: Я не понимаю проблемы, несколько уровней никак не коррелируют с количеством сущностей. Отвяжитесь от базы сначала, от API, вообще полностью от реализации. Подумайте какие действия выполняют у вас оба вида пользователей. Если они идентичны то и в предметной области у Вас один пользователь, а откуда берутся данные и как они обрабатываются вы уже решаете в инфраструктуре - то есть в реализации. Например вы делаете два репозитория DbUserRepo и ApiUserRepo, и в нем занимаетесь преобразованием. Оба репозитория вернут вам сущность пользователя. Если вам далее нужны разветвления то это уже задача обработчиков, вы проставляете пользователю источник, чтобы приложение знало как с ним работать. Например записываете при получении пользователя по API какой-нибудь type:api, а при получении из базы type:db. Далее по этому типу создаете обработчик, у которого есть например метод send, один отправляет пользователя в базу, другой через API.
Михаил: В DDD не важно откуда берутся сущности, потому что это просто сущности. И классы которые их достают в domain слое есть только в виде интерфейса. По сути это репозиторий. Только он работает не с базой, а с API. Для того чтобы понять полностью как это работает, нужно понять как отвязывать предметную область от реализации.
Михаил: Наследоваться можно только в том случае, когда замена наследника на родителя и наоборот не влияет на последующий код программы и соответственно не ломает логику работы. Дефолтный пример с прямоугольником и квадратом легко гуглится по Liskov Substitution example.
Но Yii имеет другую идеологию и применение SOLID и таких практик как DDD в нем затруднено.
Вам нужно выносить обработку пользователей в два разных класса или набора классов и с помощью фабричного метода или фабрики соответственно создавать обработчики.
Примитивный пример сделал вот здесь: sandbox.onlinephpfunctions.com/code/7ce605472b9755...
Обратите внимание, что реализация user тут абсолютна не важна в самом коде программы, она важна только для конкретного обработчика. А обработчик приводит работу с обеими пользователями к единому виду.
Надеюсь я правильно понял задачу, которая стоит перед вами.
Dmitriy Ronzhin: не понял на самом деле проблемы, у вас все скидки это стратегия, если конкретнее стратегия расчёта цены, в стратегию вы можете добавлять сколько угодно видов скидок отдельными объектами и вообще все что вам вздумается, на то она и стратегия. В зависимости от того с какими скидками вы создали стратегию, идёт её расчёт.
Михаил: А по факту информации до сих пор не хватает, сущности если разные то и классы работающие с ними разные, сущности одинаковые или одну можно привести к другой, то и классы одни и те же. Если часть кода работает и с той и с другой общую часть закрываем интерфейсом и этот интерфейс передаём в классы обработчики, остальную логику разносим. Нужена более точная формулировка чем у меня есть два вида пользователей. Нужно плясать от интерфейса
Никита: Андрей: Я не буду спорить, можно сделать все, но для этого нужно перелопатить пол фреймворка, можно использовать QueryBuilder, можно написать свой UnitOfWork. Но все это уже написано за нас и все это легче использовать с Zend и Symfony, чем интегрировать в Yii, а нужна именно интеграция из-за сильной связанности внутри фреймворка.
Yii модели охватывают много функционала - так это недостаток больше, чем преимущество. Класс должен иметь единую ответственность, а не уметь все. Но в действительности - это проблема ActiveRecord в общем.
Насчет контекста Yii. Зачем мне привязывать мою предметную область к конкретному фреймворку? Наследоваться от чего-то. Зачем? Я пишу в своих проектах предметную область на голых объектах. Закрываю репозитории интерфейсами, пишу сервисы с использованием этих репозиториев и интерфейсов нужных мне либ. Далее покрываю все это тестами мокая репозитории и эти сервисы. До этого шага у меня вообще нет никаких фреймворков, нет вообще ничего. Есть только моя бизнес задача. Которую я могу оттестировать еще до интеграции и реализации. Далее подрубаю доктрину, external mapping'ом маплю объекты на базу\кеш (при этом структура базы может быть абсолютно любой, она не привязана к моей предметной области, потому что объект не является таблицей\документом БД). Реализую репозитории, сервисы, логику самого Application Layer. И потом на это делаю сколько угодно интерфейсов (console, web, api).
И еще раз повторю, что под каждую задачу свои инструменты. Если вам хватает Yii и его идеологии, то это не значит, что всем ее хватает и всех она устраивает. Человек изучает DDD, а Yii для этого совсем не подходит, потому что DDD - это ERP паттерн, а Yii не ERP фреймворк.
Никита: и я не говорил, что реализация актив рекорд убогая. Сам по себе паттерн актив рекорд убогий, потому что он объединяет в себе бизнес логику и работу с базой. Value Object сразу в топку, независимость предметного объекта от базы в топку. Это ж не важно, но только если у вас маленькое приложение.
Извиняюсь за то что 3 сообщения. С телефона пишу :)
Никита: актив рекорд шикарный. Пока вы не столкнётесь с огромными моделями с кучей бизнес логики, ой а кеширование ещё нужно, а кастомные запросы, ещё бы хорошо события в шину кидать. Ну в общем то да, если писать сайтик то нет проблем, статику тестировать - одно "удовольствие". В общем, для каждой задачи свои инструменты. Но энтерпрайз приложений вы на yii не встретите.
Никита: промежуточные слои модели? Это что такое? Я думал мы говорим о hexagonal architecture, а не о "промежуточных слоях модели" :) Погуглите и попробуйте написать что-то более сложное чем MySQL + CRUD. Например, бухгалтерию :)
Степан: сейчас все современные дата центры работают на ssd. CDN это по сути прокси, между пользователем и Вашим сервером, которое хранит и раздаёт ваш контент максимально быстро для пользователя.
Степан да, плюс балансить базу и кеш, например twemproxy + pgbouncer. CDN решит вопрос со статикой, тем более сейчас многие умеют монтировать директорию CDN непосредственно к серверу, что очень удобно. Главное не забывать, что преждевременная оптимизация - зло, и всегда проще докупить(на время) пару серверов и развернуть на них приложение(базу/кеш/статику), чем в попыхах заниматься их оптимизацией.
У нас сейчас все тестовые стенды в докере. Но на проде деплоим фабриком(идёт переход на ансибл). Я не в курсе почему для прода не используется докер, так как сам на данном этапе не в курсе)
Пишу с телефона, поэтому могу косячить, заранее извиняюсь.
Говоря про роллбэк я имел ввиду именно мигоации, то есть юз кейс такой - выкатываем новую версию с миграциями, она оказывается забагованной(малая но вероятность есть) мы перестанавливая пакет хотим откатить и миграции. Идея с переменной окружения интересна. Изначально рассматривал дефолтную табличку в бл migrations. Соответственно и поэтому были выбраны деб пакеты так как откат на предыдущую версию приложения очень прост и реализуется на уровне дистрибутива.
Вопрос в том как эти миграции накатывать. Пока самая здравая идея которая у нас возникла, это в пакете распространять доп утилитку которая будет следить за мигрциями и запускаться в post install скрипте пакета. Но серверов много и тут может возникнуть проблема с тем что в одну базу будут стучаться несколько если использовать переменные среды, то тут уже напрашивается что то типо мастер сервера, чтобы только он накатывал миграции. Проблема предполагаемая, на практике не знаю, как это себя поведёт.
По systemd в основном вопрос как ведёт себя в нем го приложение, а если конкретнее горутины, с ними как я слышал при демонизации не работает стандартный fork. Нужно что то применять дополнительно или systemd умеет с этим бороться?
Сергей Протько: Давайте не будем человека путать, по его вопросу понятно, что с проектированием он еще не знаком =) MVC проще всего освоить на одной модели, на фрейморках типо Yii, где модель явно выражена. Понятное дело, что Вы можете вынести логику в сервисный слой, но работая над маленьким приложением или прототипом в этом нет смысла.
А насчет SOA, вопрос не в конкретной реализации, а в самом принципе независимых и инкапсулированных сервисов. Это актуально и в проектировании одного приложения. Ссылка не удачная, как и термин SOA, но этот способ является хорошим примером, как нужно проектировать своё приложение. Я наверно не правильно донес свою мысль =)