Разделение приложения на слои

Обсуждаем, как правильно строить приложения
nepster
Сообщения: 838
Зарегистрирован: 2013.01.02, 03:35

Re: Разделение приложения на слои

Сообщение nepster »

vova07 писал(а):Давно не было интересных тем на этом форуме, так что если позволите поделюсь мнением и пообщаюсь чуток с вами тут.
Гист прочитал только то что описал автор, тему эту прочитал бегло, ибо много текста.

От себя осмелюсь подправить автора и тех кто называют данный паттерн "Repository", это не так. Это как раз сервисных патерн в своей самой простой реализации с элементами репозитория.

"Repository" патерн подразумевает взаимодействие "Repository" класса с "Persistence" (хранилищем). В идеале он должен использоваться только как мост между "Aplication Layer" и хранилищем. Но не содержать избыточной логики как валидация например, или внешние функции которые используются в контролерах. Это как раз дело сервиса.

Конечно это идеальный вариант и учитывая это можно забить и согласится что описанное является "репозиторием", но наверное это больше похоже на недоделанную комбинацию между Сервисом и Репозиторием, который в идеале должен превратится в "Command" с зависимостью от "Repository".

Уверен что вам надоело моя болтовня, но по теме могу еще добавить следующее:
- При крупных проектах очень удобно разделять приложения на слои
- Лучше всего всегда использовать Repository патерн
- Лучше всего комбинировать это все с "Command" патерном и "CommandBus" классом.
- В идеале использовать для общения между слоями DTO
- Конечно если речь идет о крупных проектах то без Entity и ValueObjects (VO) мы не сможем жить.
- И конечно не забываем про "Identity Map" патерн который обязательно по моему мнению должен присутствовать в "Repository" классе.
- Ну и конечно не забываем про Exception и Marker Interface для наших собственных исключений для хорошего тона.
- Если уже дошли до радикальных мер, то не бойтесь выносить Инфрастуктуру отдельно и используйте Core Domain и чуток вашего кода для хорошего результата.
- Ну и конечно не бойтесь усложнять чуток логику, в будущем это спасет ваш проект. DDD придумали умные люди которые решали сложные задачи, не думайте что эти пару тройку классов и папок усложнят жизнь, они как раз сделают противоположное.

П.С: Почему я это написал? Просто хочется чтобы и на Уии люди писали грамотно, а то фреймворк то вроде хороший, а пишут не нем все как школники.
На сколько я понял, DDD это очень сложна штука, потому что я вообще ничего про нее не понял =).

Нам бы тут хотябы с S.O.L.I.D разобраться. Тоесть все что я понял про DDD, этот подход объединяет в себе множество подходов, такие как S.O.L.I.D, TDD, BDD и тп. По мне это пока слишком круто и слишком для крутого проекта, который выходит за рамки 1 - 2 технологий.
Аватара пользователя
vova07
Сообщения: 1004
Зарегистрирован: 2012.11.29, 14:52
Откуда: Chisinau, Moldova

Re: Разделение приложения на слои

Сообщение vova07 »

lynicidn писал(а):
vova07 писал(а): а пишут не нем все как школники.
:o
Если вы не согласны можно почитать 98% топиков на этом форуме где есть примеры кода, и убедится в этом.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Разделение приложения на слои

Сообщение zelenin »

vova07 писал(а):
lynicidn писал(а):
vova07 писал(а): а пишут не нем все как школники.
:o
Если вы не согласны можно почитать 98% топиков на этом форуме где есть примеры кода, и убедится в этом.
он намекает на отсутствие Ь в слове школьник)
Вась, без обид - твое сообщение (предыдущее) 90% прочтут как "бла-бла", а 8% как набор keywords для поиска в гугле. Вот серьезно: пользы ноль.
lynicidn
Сообщения: 2222
Зарегистрирован: 2014.05.24, 15:12

Re: Разделение приложения на слои

Сообщение lynicidn »

vova07 писал(а):
lynicidn писал(а):
vova07 писал(а): а пишут не нем все как школники.
:o
Если вы не согласны можно почитать 98% топиков на этом форуме где есть примеры кода, и убедится в этом.
многие тут не сидят, но кодят на уии и они как раз не школьники :) форумы для вопросов в основном же
Аватара пользователя
vova07
Сообщения: 1004
Зарегистрирован: 2012.11.29, 14:52
Откуда: Chisinau, Moldova

Re: Разделение приложения на слои

Сообщение vova07 »

nepster писал(а):На сколько я понял, DDD это очень сложна штука, потому что я вообще ничего про нее не понял =).

Нам бы тут хотябы с S.O.L.I.D разобраться. Тоесть все что я понял про DDD, этот подход объединяет в себе множество подходов, такие как S.O.L.I.D, TDD, BDD и тп. По мне это пока слишком круто и слишком для крутого проекта, который выходит за рамки 1 - 2 технологий.
Я полностью согласен что DDD сложен, и нужен в большинстве случаев в крупных проектах или там где сложная бизнес логика. Хотя если проект подразумевает длительную поддержку DDD вполне оправдан.

То что я написал в пунктах выше это были глобальные советы. И я не писал что нужно использовать везде DDD.

Я переформулирую свои ответ: Всегда нужно использовать правильные паттерны. Если мы будем придерживаться этой мысли код станет чище.

А вот про ДДД то в пятиминутке вроде вполне нормально высказался Ragazzo. Это принцип и идеология разработки. А те технологии и подходы которые используются при такой разработке являются непосредственными результатами решения тех или иных задач.

Кстати про SOLID, TDD и BDD не сложно почитать в интернете, там много информации и именно эти конкретные подходы не такие уж слоные в понимании. Если есть вопросы я думаю всегда можно задать их и тут уверен найдутся те кто смогут ответить.
Аватара пользователя
vova07
Сообщения: 1004
Зарегистрирован: 2012.11.29, 14:52
Откуда: Chisinau, Moldova

Re: Разделение приложения на слои

Сообщение vova07 »

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

@lynicidn я не сказал что все, а большинство. И если честно это не их вина, а сложившаяся ситуация. Большинство примеров решения задач, нацелены на непосредственный результат. И очень мало примеров где кроме результата еще учитывается и правильный подход. Вот примерно это я имел введу. Я писал про сами ответы, а не про вопросы, которые конечно естественны на любом форуме.

П.С. Саша а что сделают остальные 2 процента?
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Разделение приложения на слои

Сообщение zelenin »

vova07 писал(а):Саша, я поделился своим мнением и опытом. Если расписывать что-то из тех пунктов выйдет очень много слов. Подразумевалось что в случае интереса будут задаваться конкретные вопросы на которые можно будет получить ответы.
к сожалению твой опыт, выраженный в виде ключевых слов, не несет никакой практической пользы, поскольку именно в практическом ключе шел диалог. И даже в таком ключе это вызывало споры.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Разделение приложения на слои

Сообщение zelenin »

vova07 писал(а):@lynicidn я не сказал что все, а большинство. И если честно это не их вина, а сложившаяся ситуация. Большинство примеров решения задач, нацелены на непосредственный результат. И очень мало примеров где кроме результата еще учитывается и правильный подход. Вот примерно это я имел введу. Я писал про сами ответы, а не про вопросы, которые конечно естественны на любом форуме.
можно ведь и на yii программировать нормально, но все вокруг тебя учит yii-стайлу (конструктор сайтов по сути), и от него можно только сбежать в другое место (я о симфони например, где все о программировании - lynicidn подтвердит).
Да, примеры нацелены на результат, но как-то диссонирующе, когда ты создаешь проект, который по коду и дизайну лучше чем сам фреймворк)
(я подтверждаю твои слова, если что)
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Разделение приложения на слои

Сообщение zelenin »

vova07 писал(а):П.С. Саша а что сделают остальные 2 процента?
согласись, человек. постигший смысл твоих "ключевых слов", либо уже ушел с yii, либо ждет последнего толчка. Он уже не программирует, а проектирует.
lynicidn
Сообщения: 2222
Зарегистрирован: 2014.05.24, 15:12

Re: Разделение приложения на слои

Сообщение lynicidn »

zelenin писал(а):
vova07 писал(а):@lynicidn я не сказал что все, а большинство. И если честно это не их вина, а сложившаяся ситуация. Большинство примеров решения задач, нацелены на непосредственный результат. И очень мало примеров где кроме результата еще учитывается и правильный подход. Вот примерно это я имел введу. Я писал про сами ответы, а не про вопросы, которые конечно естественны на любом форуме.
можно ведь и на yii программировать нормально, но все вокруг тебя учит yii-стайлу (конструктор сайтов по сути), и от него можно только сбежать в другое место (я о симфони например, где все о программировании - lynicidn подтвердит).
Да, примеры нацелены на результат, но как-то диссонирующе, когда ты создаешь проект, который по коду и дизайну лучше чем сам фреймворк)
(я подтверждаю твои слова, если что)
да, проблема уии в том что каждый второй пишет "хорошии практики", а по факту все это спорно, и то что вопросы на форуме задают иной раз такие глупые, и соответственно получают аналогичные ответы, а дальше заходящие в этот топик просто размножают это копипастой
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Разделение приложения на слои

Сообщение zelenin »

lynicidn писал(а):
zelenin писал(а):
vova07 писал(а):@lynicidn я не сказал что все, а большинство. И если честно это не их вина, а сложившаяся ситуация. Большинство примеров решения задач, нацелены на непосредственный результат. И очень мало примеров где кроме результата еще учитывается и правильный подход. Вот примерно это я имел введу. Я писал про сами ответы, а не про вопросы, которые конечно естественны на любом форуме.
можно ведь и на yii программировать нормально, но все вокруг тебя учит yii-стайлу (конструктор сайтов по сути), и от него можно только сбежать в другое место (я о симфони например, где все о программировании - lynicidn подтвердит).
Да, примеры нацелены на результат, но как-то диссонирующе, когда ты создаешь проект, который по коду и дизайну лучше чем сам фреймворк)
(я подтверждаю твои слова, если что)
да, проблема уии в том что каждый второй пишет "хорошии практики", а по факту все это спорно, и то что вопросы на форуме задают иной раз такие глупые, и соответственно получают аналогичные ответы, а дальше заходящие в этот топик просто размножают это копипастой
хороший пример твоих слов ситуация с модулями на заре зарождения yii2. а) Для чего нужны модули? Для переносимости из проекта в проект. б) Как их юзать в advanced? Пихать в common, наследоваться в backend и frontend. Это называлось хорошей практикой, только а) с б) не сочетается, да и сам б) как оказалось от слова "бред".
nepster
Сообщения: 838
Зарегистрирован: 2013.01.02, 03:35

Re: Разделение приложения на слои

Сообщение nepster »

vova07 писал(а):
nepster писал(а):На сколько я понял, DDD это очень сложна штука, потому что я вообще ничего про нее не понял =).

Нам бы тут хотябы с S.O.L.I.D разобраться. Тоесть все что я понял про DDD, этот подход объединяет в себе множество подходов, такие как S.O.L.I.D, TDD, BDD и тп. По мне это пока слишком круто и слишком для крутого проекта, который выходит за рамки 1 - 2 технологий.
Я полностью согласен что DDD сложен, и нужен в большинстве случаев в крупных проектах или там где сложная бизнес логика. Хотя если проект подразумевает длительную поддержку DDD вполне оправдан.

То что я написал в пунктах выше это были глобальные советы. И я не писал что нужно использовать везде DDD.

Я переформулирую свои ответ: Всегда нужно использовать правильные паттерны. Если мы будем придерживаться этой мысли код станет чище.

А вот про ДДД то в пятиминутке вроде вполне нормально высказался Ragazzo. Это принцип и идеология разработки. А те технологии и подходы которые используются при такой разработке являются непосредственными результатами решения тех или иных задач.

Кстати про SOLID, TDD и BDD не сложно почитать в интернете, там много информации и именно эти конкретные подходы не такие уж слоные в понимании. Если есть вопросы я думаю всегда можно задать их и тут уверен найдутся те кто смогут ответить.
Почитать и разобраться, то не проблема. А вот выработать привычку и правильный подход к разработке по данным методологиям это уже другой вопрос.
Я например уже несколько лет пытаюсь разобраться с тестами и каждый раз себе говорю щас вот начну писать, но как только начинается новый проект с малейшим намекам на сроки, написание тестов автоматически забывается и переносится на 100500 план.

И когда появляются бизнес-ситуации в 99% случаях, когда кровь из жопы завтра это должно работать, потому что послезавтра это никому не нужно, то тут уже не до проектирования, тестов и методологий.
lynicidn
Сообщения: 2222
Зарегистрирован: 2014.05.24, 15:12

Re: Разделение приложения на слои

Сообщение lynicidn »

без обид des1roer, активно задающий вопросы на форуме и в гиттере.
тут я на днях наткнулся на его учебник http://des1roer.blogspot.ru/2015/06/yii2.html
кого и чему может научить человек? а ниже камент от elisdn что это вообще копипаста от githubjeka
так вот и учятся новички
Аватара пользователя
vova07
Сообщения: 1004
Зарегистрирован: 2012.11.29, 14:52
Откуда: Chisinau, Moldova

Re: Разделение приложения на слои

Сообщение vova07 »

Чтобы загладить вину приведу пример с кодом который чуток разъяснит ситуацию.
Пример ограничен рамками Уии, чтобы он был более менее компактным и актуальным для данного топика и форума:

Условие:
Написать модуль комментариев.
Рассматриваемая сторона:
Пример реализации одного или очень ограниченого количества методов. (Для экономии текста)

Описание логики словами:
- Уии фреймворк все еще служит основой нашего приложения. И вся работа строго в духе Уии.
- Роутер принимает запрос и запускает нужный экшен.
- Экшен контролера содержит минимальный код. И делает минимальное количество действий.
+ Обычно это заполнение DTO, в нашем случае это больше похоже на POCO и в рамках Уии это обычно называется форма. Учитывая функционал предоставляемый фреймворком форма содержит и валидацию.
+ После заполнения формы, она передается в "Command" (Команду) которая делает то для чего она была создана.
+ В конце просто отправляем ответ. Важно понять что ответ в идеальных условиях должен быть получен из другой комнады, чтобы соблюдался принцип SRP. В нашем случае мы это упустим, чтобы не усложнять все сильно. Кому интересно будет можете прочитать про CQRS.
- В момент вызова комманды, в хорошей архитектуре вызывается её обработчик, который и выполняет нужные действия.
+ Обычно это валидация данных
+ Выполнения непосредственно того действия для которого эта команда была создана, в нашем случае это создание комментария. нужно заметить что непосредственная создание комментария реализована через "Repository" (Репозиторий) который служит как абстракция от "Persistence" (Хранилища).
- Репозиторий выполняет сохранения данных в выбранное хранилище. (Если есть ситуации когда нужны разные скоупы и типы выборок, то именно репозиторий должен этим заниматься)

Словарь:
- Репозиторий = Repository class, реализация Repository Pattern -> YiiRepository
- Хранилище = Persistence, в большинстве случяев это БД. И чаще всего это MySQL
- Команда = Command class, реализация Command pattern -> CreateCommentCommand и LoadCommentCommand
- Сущность = Entity class -> AR модель комментария (Comment)
- Форма = Форма комментария которая наследуется от Model

Реализация:

Код: Выделить всё

// CommentsController
...
public function getRepository()
{
    return new YiiRepository();
}

public function actionCreate()
{
    $form = new CommentForm();
    $form->load(Yii::$app->request->post());
    
    $repository = $this->getRepository();
    $aCommentId = $repository->nextIdentity();
    
    $command = new CreateCommentCommand($repository);
    $command->handle($aCommentId, $form);
    
    $query = new LoadCommentCommand($repository);
    $comment = $query->handle($aCommentId);
    
    return $comment;    
}
...

// CreateCommentCommand
...
public function __construct(IsRepository $repository)
{
    $this->repository = $repository;
}

public function handle(ObjectId $anId, Form $aForm)
{
    $comment = $this->repository->newComment($anId, $aForm);
    $this->repository->store($comment);
}
...

// YiiRepository
...
public function newComment(ObjectId $anId, Form $aForm)
{
    $comment = new Comment();
    $comment->setAttributes($aForm->getAttributes());
    $comment->id = $anId->value();
    
    return $comment;
}

public function store(Comment $aComment)
{
    $aComment->save(false);
}

public function getById(ObjectId $anId)
{
    return Comment::find(['where', 'id' => $anId->value()])->one();
}
...

// Comment
class Comment extends ActiveRecord {
    # При хорошем тоне тут должны быть только атрибуты и АР должна играть роль сущности (Entity)
}
Итог:
- Весь код писалься сразу сюда без проверок, так что он чисто для демонстративных целей.
- Код не является идеальным, и его можно еще очень хорошо улучшить.
- Данный пример только улучшает подход разработки на Уии фрейме, но он не идеален так как он все еще придерживается Уии стайлу.
- Это примерные наброски реальных практик которые могут встречаться в проектах которые все еще завязаны на фреймворке, но уже отрефакторили часть своей бизнес логики.

От себя:
Я чисто поделился мнением и опытом, и хотел просто пообщаться на интересную тему, если кому-то это показалось пустой тратой времени, то уж извините.
nepster
Сообщения: 838
Зарегистрирован: 2013.01.02, 03:35

Re: Разделение приложения на слои

Сообщение nepster »

У меня просьба к модераторам:

Перенесите пожалуйста тему в другой раздел, например viewforum.php?f=28

Тема интересная и является дискуссией, а не конкретным вопросом и в текущем разделе "Общие вопросы" она просто потеряется.
lynicidn
Сообщения: 2222
Зарегистрирован: 2014.05.24, 15:12

Re: Разделение приложения на слои

Сообщение lynicidn »

извиняем :D
переходим на симфони2? )
На самом деле веб контроллер у тебя и ничего страшного что он отдаст строку вместо респонзе объекта и я так понимаю *Command extends Model ?
а не слишком много моделей? почему не уместить все в $form ?
подход интересен за исключением того, что вы хотите убить 2х зайцев сразу, универсальный контроллер, но они разные изначально yii/console yii/web - тут я не заморачиваюсь и это остается в уии стайл, если вы не ставите цель шифровать уии код, то смысда в этом 0

я тоже не работаю с ар в контроллерах, почти, там где нужна обработка пользовательского ввода - у меня 1 модель форма (как правило) и сценариями и методами это модели уже работаю в контроллере, выглядит в уии стайл с соблюдением BC (совместимо с gii)
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Разделение приложения на слои

Сообщение zelenin »

https://github.com/dddinphp в тему.
кто купит книгу, расшарьте для коллег)
Аватара пользователя
vova07
Сообщения: 1004
Зарегистрирован: 2012.11.29, 14:52
Откуда: Chisinau, Moldova

Re: Разделение приложения на слои

Сообщение vova07 »

lynicidn писал(а):извиняем :D
переходим на симфони2? )
На самом деле веб контроллер у тебя и ничего страшного что он отдаст строку вместо респонзе объекта и я так понимаю *Command extends Model ?
а не слишком много моделей? почему не уместить все в $form ?
подход интересен за исключением того, что вы хотите убить 2х зайцев сразу, универсальный контроллер, но они разные изначально yii/console yii/web - тут я не заморачиваюсь и это остается в уии стайл, если вы не ставите цель шифровать уии код, то смысда в этом 0

я тоже не работаю с ар в контроллерах, почти, там где нужна обработка пользовательского ввода - у меня 1 модель форма (как правило) и сценариями и методами это модели уже работаю в контроллере, выглядит в уии стайл с соблюдением BC (совместимо с gii)
Нет почему переходить? Я нигде не упоминал призыв к переходу. Если код становится чуток похоже на симфони это не значит что нужно туда переходить. Кстати это не симфони стайл, а допотопный ДДД стайл. Просто по обстоятельствам так сложилось что это напоминает Симфони.

Команда не наследуется от модели. Это обычный класс который ни от чего не наследуется. А тупо имплементить интерфейс команды для целестности.

Моделей может и много но это если придерживаться Уии стилю. Если использовать DTO + Assembler и делать валидацию в отдельном слое, то от моделей можно полностью избавится. Напоминаю что код который я написал все еще сохраняет Уии стайл для понимания мыслей сообществом, и он все еще зависит от фрейма, но если серьезно подойти к архитектуре и спроектировать по всем правилам то мы получим Уии классы только в "Infrastructure" слое. Некоторые классы будут в UI подслое этого слоя, а другие в "Persistance" и все. Кор у нас будет чистым и 100% независимым.

Форма и команда в данном случае полностью независимы и они имеют разные цели.
Напишу подробнее:
- форма это сборщик данных, саму форму можно заменить обычным массивом данных ибо $form->getAttributes() именно это и возвращает. Но так как асемблера у нас нету в примере, форма служит некой POCO реализацией.
- Что касательно команды, она по сути зависит от формы, но как я сказал это по сути обычный массив данных, таким образом команда делает свое дело независимо от формы. Что это нам дает? В любой момент можно изменить логику работы просто изменив в мапинге класс комнады. (Это в случае с тем убогим примером что я показал), в идеале это должно оставаться неизменным и решатся на уровне CommandBus и его мапинга.

Касательно контролеров то я не имел такой цели хотя в реали да, это так. Суть правильного проектирования в том чтобы получить независимый код. Реальный пример это тестирование кода. Если у нас в контролере есть зависимости от пользователя и они не работают через DI, то тестирование такого кода превращается в ад. А по сути console и web отличаются именно такими мелочами. Или те же Response/Request, которые при таком подходе можно очень легко подменить.

Код сырой и чисто для примера, если у кого есть более конкретные вопросы я смогу по мере возможности ответить.
Аватара пользователя
vova07
Сообщения: 1004
Зарегистрирован: 2012.11.29, 14:52
Откуда: Chisinau, Moldova

Re: Разделение приложения на слои

Сообщение vova07 »

zelenin писал(а):https://github.com/dddinphp в тему.
кто купит книгу, расшарьте для коллег)
Если найду её у себя в доках скину ссылку для скачивание.
ShNURoK
Сообщения: 168
Зарегистрирован: 2012.04.12, 05:44
Контактная информация:

Re: Разделение приложения на слои

Сообщение ShNURoK »

zelenin писал(а):вообще файндеры - это удел Репозитория. Но и скоупы - это тоже удел репозитория. Но в Query файндеров быть не должно. Исходя из этого делайте, как считаете правильным.
По репозиториям нашел ссылку для laravel http://heera.it/laravel-repository-pattern может кому-то будет интересно, суть одна.
Закрыто