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

Обсуждаем, как правильно строить приложения
lynicidn
Сообщения: 2222
Зарегистрирован: 2014.05.24, 15:12

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

Сообщение lynicidn »

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

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

Сообщение nepster »

Sam Dark писал(а):nepster
Выдавайте интересующие вас вопросы. Только менее абстрактные и масштабные. Не «как мне структурировать мой доменный слой» или «как не погрязнуть в говнокоде», а «куда положить вот этот код» или «вот это делать в модели, вию или контроллере?». Отвечу и закину в гайд в виде примечаний.

Если попытаться впихнуть «как надо слоить и надо ли» в гайд, там набежит на серию книг.
Было бы здорово. Давайте попробуем.

1) Где размещать геттеры на реляции ?
Проблема следующая:
Я использую шаблон advanced. Предположим, что Есть модель Apartment как в common так и в bakend и frontend.
Теперь предположим, что у нас есть некоторые методы, которые перекрыты для frontend и bakend. Например отображения адреса.
в common модель Apartment содержит выборки и реляции.

Если сделать выборку через модель frontend/Apartment мы получим common модель (так как метод выборки именно в ней). ПОэтому что бы получить доступ к перекрытому методу, я использовал позднее статическое связывание. А что бы все это правильно работало, пришлось дублировать все реляции из common в frontend и bakend. Основная причина в том, когда мы делаем выборку из frontend/Apartment и спользуем много джоинов все джоины будут тоже из frontend.

Но остался дискофорт из-за дублей реляций.


2) Helper vs Method?
Мыло много вопросов и споров по теме, например: viewtopic.php?f=19&t=31240
Тут советуют завести хелпер.

Но куда удобнее сделать просто вот так:

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

echo $model->fullName
чем:

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

use \app\helpers\UserHelper
echo UserHelper::getFullName($model);
 

3) Где размещать методы выборки ?
Если выборок может быть очень много с разными вариантами, хорошо было бы их в отдельный файл выкинуть. Я попробовал это сделать несколько сообщений назад, но походу остальным это не очень понравилось.
viewtopic.php?f=28&t=31100&start=80#p160893

Для справки, сейчас 90% разработчиков пихают их где попало. Хорошо если в контроллере, плохо если в представлении. Я же стараюсь почти всегда это дело инкапсулировать (за исключением SearchModel и FormModel).
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

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

Сообщение zelenin »

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

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

Сообщение nepster »

Да ну причем тут папка ? Как это дело вызывать, ну например я сделал в вешепоказанном примере класс-репозиторий для выборок, положил туда выборки, и в моделе сделал на него геттер. Тебе вроде тоже не понравилось.
Я щас заканчию проект, там после полу года разработки достаточно жирные модели получились, это не смотря на то, что есть разделение на FormModel, SearchModel и тп.

Папки тут особой роли не играют, основная суть вопроса, как это все дело вызывать и потом не забыть через время что вообще и куда было налеплено.
Аватара пользователя
xoma
Сообщения: 641
Зарегистрирован: 2009.04.02, 15:24
Откуда: Ногинск
Контактная информация:

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

Сообщение xoma »

Вообще, имхо, делить модели (читай entity) на backend и frontend - это зло.
Сущность она одна и не имеет значения в админке она или на фронте.
nepster
Сообщения: 838
Зарегистрирован: 2013.01.02, 03:35

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

Сообщение nepster »

xoma писал(а):Вообще, имхо, делить модели (читай entity) на backend и frontend - это зло.
Сущность она одна и не имеет значения в админке она или на фронте.
А я если разная логика ?
Например для админки нужно все тоже самое + прикрутить поведение, которое делает записи "что там натворил админ"?
Или адрес для фронтенда обычный, а для админки с ссылкой ?

И еще очень много вариантов, которые могут быть разными в зависимости от фронтенда и бэкенда.

И я что-то не могу прикинуть как сделать так, что бы не трогать модель постоянно.
Аватара пользователя
xoma
Сообщения: 641
Зарегистрирован: 2009.04.02, 15:24
Откуда: Ногинск
Контактная информация:

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

Сообщение xoma »

Ну поведения, тоже зло =) Насчет логирования действий админа. Я делал примерно вот так: модель генерит событие "Я поменялась" в backend-приложении есть листенер, который это событие слушает и делает логирование изменений. На frontend приложении такого листинера нет.

Адрес это что? Url ? Модель вообще не должна ничего про генерацию урл знать, с моей точки зрения.
nepster
Сообщения: 838
Зарегистрирован: 2013.01.02, 03:35

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

Сообщение nepster »

xoma писал(а):Вообще, имхо, делить модели (читай entity) на backend и frontend - это зло.
Сущность она одна и не имеет значения в админке она или на фронте.
Вот например тут все подряд есть и логика и выборки и он инклюзив:
https://github.com/yupe/yupe/blob/maste ... omment.php

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

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

Сообщение nepster »

xoma писал(а):Ну поведения, тоже зло =) Насчет логирования действий админа. Я делал примерно вот так: модель генерит событие "Я поменялась" в backend-приложении есть листенер, который это событие слушает и делает логирование изменений. На frontend приложении такого листинера нет.

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

https://github.com/yupe/yupe/blob/maste ... t.php#L321
Аватара пользователя
xoma
Сообщения: 641
Зарегистрирован: 2009.04.02, 15:24
Откуда: Ногинск
Контактная информация:

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

Сообщение xoma »

nepster писал(а):
xoma писал(а):Вообще, имхо, делить модели (читай entity) на backend и frontend - это зло.
Сущность она одна и не имеет значения в админке она или на фронте.
Вот например тут все подряд есть и логика и выборки и он инклюзив:
https://github.com/yupe/yupe/blob/maste ... omment.php

А если бы этот модель был по жирнее и модель в 3000 строк, уже было бы не комфортно.

Оо ну зачем вы показываете это =) Мне больно, этому коду много много лет, его хочется весь порефакторить, но нет пока возможности =)
Аватара пользователя
xoma
Сообщения: 641
Зарегистрирован: 2009.04.02, 15:24
Откуда: Ногинск
Контактная информация:

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

Сообщение xoma »

Зачем вы ссылаетесь на Юпи ? Я не говорил, что там идеал кода, там напротив дикая салянка, надеюсь в двойке будет лучше =)
nepster
Сообщения: 838
Зарегистрирован: 2013.01.02, 03:35

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

Сообщение nepster »

Так весь смысл в том, что сколько бы не было методологий, всеравно их соблюдают в 99% только в библиотеках и расширениях.
Я не видел еще ни одно проекта с супер чистым кодом, но было бы здорово сделать именно для yii2, какой-то задокументированный подход, чтобы дышать слало легче.

По поводу старого кода, все эти паттерны, методологии и тп (большинство из них), появились еще в 80 - 90 годах до существования php.
Аватара пользователя
xoma
Сообщения: 641
Зарегистрирован: 2009.04.02, 15:24
Откуда: Ногинск
Контактная информация:

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

Сообщение xoma »

nepster писал(а):Так весь смысл в том, что сколько бы не было методологий, всеравно их соблюдают в 99% только в библиотеках и расширениях.
Я не видел еще ни одно проекта с супер чистым кодом, но было бы здорово сделать именно для yii2, какой-то задокументированный подход, чтобы дышать слало легче.
Ключевая ошибка в фразе "именно для yii2". Если Вы хотите писать правильный код, фреймворк должен быть вообще не важен.
Для примера посмотрите на https://github.com/elcodi и в частности на https://github.com/elcodi/elcodi/tree/m ... /Component
Идеальных проектов, как и каких-то универсальных серебряных пуль нет.
nepster писал(а): По поводу старого кода, все эти паттерны, методологии и тп (большинство из них), появились еще в 80 - 90 годах до существования php.
А это тут при чем ? Код, подход к разработке, философия, мудрость в конце концов, все это растет вместе с разработчиком.
Да, есть уникумы, которые сходу пишут хороший код, но большинство (имхо) учится на своих шишках и на своем говнокоде.
Вот вы, подняв, эту тему учитесь и стараетесь, а есть те, кто как писал 10 лет назад, так и пишет до сих пор =)
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

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

Сообщение samdark »

1) Не всё то дубли, что похоже на дубли. Если там реально отличающиеся модели, делаем разные. Если нет — одну в common.
2) Делайте как удобней. В этом случае геттер в модели логичнее.
3) Если вы про методы аля scope, то в Query-классе. Это в документации расписано. Если есть желание и необходимость, можно репозиторий завести. Я бы репозиторий либо сунул в Yii::$app->..., либо использовал DI чтобы получить его инстанс.
nepster
Сообщения: 838
Зарегистрирован: 2013.01.02, 03:35

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

Сообщение nepster »

Sam Dark писал(а):1) Не всё то дубли, что похоже на дубли. Если там реально отличающиеся модели, делаем разные. Если нет — одну в common.
2) Делайте как удобней. В этом случае геттер в модели логичнее.
3) Если вы про методы аля scope, то в Query-классе. Это в документации расписано. Если есть желание и необходимость, можно репозиторий завести. Я бы репозиторий либо сунул в Yii::$app->..., либо использовал DI чтобы получить его инстанс.
Александр, а вы можете привести пример как можно использовать репозиторий или тот-же DI именно на практике?
Потому, как я сколько я не читал про DI, да и слышал со стороны, что DI в Yii2 это не совсем тот DI о котором (классический).

Еще если вернуться к сервисам и посмотреть на эту тему: viewtopic.php?f=19&t=31066
Потом увидеть вот этот пример https://github.com/dmitrik86/testapp/bl ... ervice.php (который как я понял посоветовали сделать), можно прикинуть, что это совсем не тот сервис о котором мы говорили (ну или я имел ввиду) изначально

Тоесть там как была зависимость так и остается, так как я понял сервис должен общаться по интерфейсам. Иначе смысла в нем нет, да еще теряется возможность использовать события актив рекорда.

Читая все ответы по теме и сравнивая практическую работу над проектами, разделения на сервисы вообще может не понадобиться до реально сложного проекта, где нужно выносить логику и делать так сказать фреймворко-независимый код.
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

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

Сообщение samdark »

DI в Yii это тот же DI, что и везде: https://github.com/yiisoft/yii2/blob/ma ... ntainer.md

На практике используется как написано в статье:

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

namespace app\controllers;

use yii\web\Controller;
use app\components\PostRepository;

class PostController extends Controller
{
    protected $posts;

    public function __construct($id, $module, PostRepository $postRepository, $config = [])
    {
        $this->posts = $postRepository;
        parent::__construct($id, $module, $config);
    }

    public function actionView($id)
    {
        $post = $this->posts->getByID($id);
        // 
    }
}
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

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

Сообщение samdark »

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

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

Сообщение nepster »

Sam Dark писал(а):DI в Yii это тот же DI, что и везде: https://github.com/yiisoft/yii2/blob/ma ... ntainer.md

На практике используется как написано в статье:

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

namespace app\controllers;

use yii\web\Controller;
use app\components\PostRepository;

class PostController extends Controller
{
    protected $posts;

    public function __construct($id, $module, PostRepository $postRepository, $config = [])
    {
        $this->posts = $postRepository;
        parent::__construct($id, $module, $config);
    }

    public function actionView($id)
    {
        $post = $this->posts->getByID($id);
        // 
    }
}
 
А зачем так сильно усложнять, если например можно сделать:

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

namespace app\controllers;

use yii\web\Controller;
use app\components\PostRepository;

class PostController extends Controller
{
    protected $posts;

    public function init()
    {
        $this->posts = new PostRepository();
        parent::init();
    }

    public function actionView($id)
    {
        $post = $this->posts->getByID($id);
        // 
    }
}
 
Что то мне кажется эта любимая абстракция только тормозит приложения и делает его медленным, например:
1) PDO - обертка интерфейс для доступа к базам данных SQL
2) Query Builder - обертка над PDO
3) Active Record - обертка над Query Builder
4) наши разработки - обертка над Active Record
5) особенно если это все REST api, которое используется в другом проекте, в котором есть обертка над этим апи, которое оборачивается еще в какие-т оразработки.

Может быть где-то это и удобно, но это все очень сильно тормозит само приложение и выжимает ресурсы.


Честно говоря я не нашел для себя возможность где можно использовать DI, кроме как перекрывать конфигурация различных виджетов и компонентов.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

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

Сообщение zelenin »

nepster писал(а): А зачем так сильно усложнять, если например можно сделать:
потому что di употребляется в паре с IoC (inversion of controle/инверсия контроля) , т.е. разработчик контроллера не должен ограничивать разработчика приложения в реализации репозитория. Он пишет интерфейс, прописывает его в качестве зависимости в конструкторе контроллера, а разработчик приложения в di прописывает в качестве реализации интерфейса свою реализацию репозитория, которая собственно с помощью di и попадет в конструктор. Например может быть две реализациии: для AR и для DAO, но контроллеру это не важно - ему нужен метод getById().
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

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

Сообщение samdark »

Если у нас 100% будет только одна реализация, особо не за чем. Если вероятна ситуация, когда потребуется заменить компонент на другой с таким же интерфейсом — есть смысл.

Главный минус абстракции не в производительности (хоть и не без этого), а в том, что код становится более «расплывчатым». Понимать и отлаживать его несколько сложнее.

Если для себя не нашли смысла применить DI, значит в вашем случае его и нет. Но попробовать стоит. Хотя-бы ради того, чтобы когда понадобится, вы знали, как это делается.
Закрыто