как Разбивать базу проекта на Domain и Application Logic

Я в замешательстве книгу Domain Driven Design Эванса я не читал но вижу в статьях о ней что он предлогает разбить программу на 4 слоя

Presentation Layer
Application (Service) Layer
Domain (Business) Layer
Data Storage Layer

Есть еще статья эта идея не нова ИМХО есть статья Multitier architecture на википедии об том же самом, только вот одно но такое деление это будет соответствовать принципам ООП?

Как это реализовать, а именно разбить на Application и Domain слои есть какие-то примеры?
И зачем нужно Data Storage Layer понятно чтобы можно было легко поменять базу данных, но можно же сделать Wrapper зачем целый отдельный механизм заталкивания в базу какой в этом смысл?
 

fixxxer

К.О.
Партнер клуба

fixxxer

К.О.
Партнер клуба
Первую можно скачать бесплатно прямо официально с сайта, там есть кнопочка.
Вторую можно скачать бесплатно с торрентов :)
 

Вурдалак

Продвинутый новичок
Учитывая вчерашнюю тему, я бы не рекомендовал сейчас смотреть в эту сторону. Просто исходя из моего личного опыта, разработчики далеко не сразу в это въезжают, у нас в компании приходится делать ревью и обсуждения по полдня, чтобы привести всё в более-менее приемлемый вид. При этом, их никто не просит так структурировать код и писать а-ля DDD, тебя встречают с сюрпризом уже на ревью. И проблема в том, что они пытаются мимикрировать под DDD, а это намного хуже обычного классического говнокода. Они уделяют много времени несущественным деталям, делают интерфейсы репозитория и прочего, но при этом модель выглядит как кусок говна.

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

В DDD нет ничего магического и сакрального, сама по себе тема очень простая и ничего особо нового для тебя не будет, если ты будешь хорошо понимать ООП. Просто ты начнёшь смотреть на вещи немного под другим углом, но для этого, повторюсь, придётся поговнокодить и скорее всего не один год. Либо иметь какого-то очень прошаренного коллегу, который будет терпеливо всё объяснять. Тут нужно много общения, поиск правильной модели и нейминга.
 

fixxxer

К.О.
Партнер клуба
Из общих соображений и интуитивно я согласен. Но вообще задумался, а так ли это? Может, въехать мешает как раз опыт говнокодинга по практикам а-ля рельсы, которые становятся шаблоном и мешают мыслить иначе?
 

Вурдалак

Продвинутый новичок
«Рельсы» всегда будут популярны, потому что моделирование — это, объективно, менее приоритетная проблема, поскольку большинство сайтов вполне себе работает и с кривыми моделями. Учитывая, что образования на тему моделирования нет, то к моделированию приходят значительно позже, чем к технологиям/алгоритмам. Я слишком скептически отношусь к мысли, что новичку можно объяснить DDD, когда его по-прежнему беспокоят низкоуровневые проблемы. Новичок в восторге от фреймворков, он будет ходить на различные бесполезные Yii/Laravel/Symfony-конференции и смотреть видео, где рассказывают как решить простую скучную практическую задачу. Люди так устроены и вряд ли тут что-то можно изменить.
 

Adelf

Administrator
Команда форума
Я программирую профессионально уже почти 15 лет и до сих пор не могу сказать, что я хоть на каком-то уровне понимаю DDD.
Большинство задач решаются без эти высоких материй. Приходишь в проект который разросся и из-за рельсового подхода еле дышит. Начинаешь просто делить по слоям и народ даже в них въезжает с трудом хотя и видит профит. Про DDD я уж молчу. Весьма редко нужный скилл. Но для определенных приложения весьма профитный.
Новичку.. даже если он вдруг поймет DDD и начнет мыслить DDD-мышлением, просто будет невозможно работать в команде. Ибо там почти всегда совсем другое мышление и подход.
 

Вурдалак

Продвинутый новичок
Да ладно, называть методы бизнес-глаголами, а не CRUD — это «редко нужный скилл»?
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Я программирую профессионально уже почти 15 лет и до сих пор не могу сказать, что я хоть на каком-то уровне понимаю DDD.
.
Ходят слухи, что если начать писать тесты, потом без DDD тяжело.
«Проверять я это конечно не буду.» ©
 

Adelf

Administrator
Команда форума
@Вурдалак, мне мож команды такие попадаются... только в одной все приняли глагольный стиль апи и, соответственно, команд и методов, который я предложил и попросили написать Code Guidelines как и куда код кидать(слои) и как называть. В остальных никто этого не понимал :) и забивали.. и получалась лапша в стиле кода.

Ходят слухи, что если начать писать тесты, потом без DDD тяжело.
О да. На текущий проект меня пригласили писать тесты :) Показали контроллер на 3к строк и попросили "покрыть его юнит-тестами" :)
 

флоппик

promotor fidei
Команда форума
Партнер клуба
О да. На текущий проект меня пригласили писать тесты :) Показали контроллер на 3к строк и попросили "покрыть его юнит-тестами" :)
Ну просто ценник умножаешь на число строк в контроллере :D
 

Вурдалак

Продвинутый новичок
только в одной все приняли глагольный стиль апи
На самом деле, команды сами по себе действительно не очень нужны, если нет событий, а происходит просто изменение модели. Когда ты делаешь событие, то тебе нужно точно понимать, какой это именно use case и от него отталкиваться, ведь иногда команды меняют модель одинаково, но с разным событиями. Скажем, я могу «удалить» модель по-разному: потому что она заэкспайрилась, потому что пользователь выразил явный отказ от предложения или потому что на пользователя наложены штрафные санкции. Технически, всё три могут вести к одному и тому же DELETE statement, но письма, например, отправляться будут разные.

Поэтому чтобы кого-то убедить, нужно найти такие use case'ы, а они точно будут в любом более-менее большом проекте.
 

Adelf

Administrator
Команда форума
Так в том то и дело, что размер и сложность проекта должны стать выше какого-то порога, когда весь этот олл-ин-контроллер код начинает крошиться из-за мелких изменений. Вот только люди, которые не знают как по-другому, считают это нормальным и даже признаком крутости проекта! Начинаются всякие анекдотики в стиле "солнце встает каждый день? не трогай ничего!"
Я все это к чему... набить шишки наверно надо. Что-то не верится мне в вундеркидов, которые сразу правильно пишут.
 

WMix

герр M:)ller
Партнер клуба
набить шишки наверно надо
Мне почемуто кажется что все наоборот, вся проблема в том, что много лишнего мы изучаем, всякие http, базы данных, сессии, струессии, а нужно было сразу обернуть это все и спрятать под капотом, а начинать с домена, медленно наслаивая проблемы.
 

ivanov77

Новичок
Начинаешь просто делить по слоям и народ даже в них въезжает с трудом хотя и видит профит.
@Вурдалак, мне мож команды такие попадаются... только в одной все приняли глагольный стиль апи и, соответственно, команд и методов, который я предложил и попросили написать Code Guidelines как и куда код кидать(слои) и как называть.
Не подскажите как делить на слои? Или где это хорошо рассказано, в книге какой нибудь.
Я на Yii2 пока работаю, у него слоев нет, и уже пришел к тому чтобы из контроллеров (да и AR моделей) логику поубирать на Service Layer, много уже читал, но везде все по разному, все эти имхо, в результате так и не сильно понятна вся картина. Эванса тоже читал, но там в общих словах и без конкретики и мало объяснений по слоям, видимо предполагается что это уже где то ранее выучено.
Ведь на практике куча вопросов начинает возникать, наподобие:
- какую логику оставить в контроллере, например формы и их валидация - это все тут или форму всю как DTO передавать в сервис и там валидировать. А всякие например сообщения в сессию, тоже только тут или в SL можно.
Плюс даже всякие пагинации и фильтры, как и где это все встраивать.
- SL - это же уже модель? Но какую туда логику точно помещать, а какую в домен. Чисто UseCase-ы в SL помещать, было кодом алгоритма в контроллере, стало объектом usecase-а?
- можно как то по простому чтобы обойтись без репозиториев, а продолжать AR объектами работать на SL?
- как общаться контроллеру с SL, видел что из SL кидают исключения домена, а в контроллере ловят, анализируют, но как то громозко выглядит. Простые альтернативы есть? Типа $service = new SomeService(); $service->run(); switch ($service->getResult()) {}...
- Как связь между уровнями определять, что можно что нельзя. Тут я так понимаю и механизм сообщений кто то использует.
- Плюс где какие объекты создаваться должны.
и т.д. и т.п.
 

fixxxer

К.О.
Партнер клуба
Ты совершаешь ошибку, которую совершают многие, кто знакомится с DDD (и я через это тоже проходил) - концентрируешься на "технической" стороне вопроса. Это, на самом деле, не так важно. Суть DDD не в этом, а в моделировании в соответствии с предметной областью на языке предметной области. Ключевые концепции - ubiquitous language и bounded context. Это можно начинать делать и оставаясь в рамках Active Record и Rails-подобного MVC, минимально необходимые модификации которых диктуются принципами моделирования (отход от анемичных моделей и REST-like API). А там уже, заметив неудобства, начнешь понимать, зачем нужны "технические" паттерны из DDD-арсенала.

Кстати, в рамках DDD вполне могут существовать и анемичные модели, просто они низводятся до голых структур данных и перестают называться моделями. Например, так получается на Javascript/Typescript, если использовать приемы функционального программирования и библиотеки управления состоянием типа Redux. Техническая сторона меняется, а принципы моделирования - нет.
 
Последнее редактирование:

WMix

герр M:)ller
Партнер клуба
представь на секунду что YII2 и его прикручивание к вашему проекту это уровень аппликации. Active Record это вероятно смешанная часть уровня хранения и домена.
твой контроллер вызывает сервис. с этого момента в классах (service) нет слов типа "use Yii2\... и подобного", с этого момента только по существу. только заказы, продукты и слова с этим связанные. если начинаешь писать "select * from" - подобные конструкции (которые относятся к хранению) вырезай в другой (маппера подобный) класс.
с этого момента приблизительно так: $(маппера подобный)->дай(критерий пойска)->сделай().

PHP:
public function addPosition( $order_nr, $product_nr, $qty ){
  $order = $this->orderProvider->getOrderByNr($order_nr);
  $product  = $this->productProvider->getProductByNr($product_nr);
  $order->addPosition( $product, $qty );
  //  $order->save(); как там у тебя в AR
}
 

ivanov77

Новичок
Да меня в общем то пока не ddd интересует, а только разделение на слои и подход с Service Layer и как все это варится.
 
Сверху