Сервисы и репозитории. Слоистая архитектура. Примеры.
Сервисы и репозитории. Слоистая архитектура. Примеры.
Знаю, что подобные темы уже были. Однако, решил открыть данную тему, чтобы люди, который "знают толк" в построении правильной архитектуры приложения (сайта) на yii2 могли поделиться примерами кода. Это очень важно, чтобы такие примеры были в одной теме, потому-что вся информация разрознена и приходится собирать ее по кусочкам по всему интернету и на форуме.
Поэтому, если Вы сильны в архитектуре и можете поделиться с сообществом кодом, как лучше организовать модели и контроллеры, как оформить классы сервисов и репозиторием, уменьшив тем самым зависимость от фреймворка - прошу поделиться опытом в данной теме.
Поэтому, если Вы сильны в архитектуре и можете поделиться с сообществом кодом, как лучше организовать модели и контроллеры, как оформить классы сервисов и репозиторием, уменьшив тем самым зависимость от фреймворка - прошу поделиться опытом в данной теме.
Разработка на yii2 или чистом php.| email: [email protected] | skype: for-web1
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
слоистая архитектура подразумевает под собой слабую зависимость от фреймворка, и по сути реализуется везде одинаково. Поэтому берем любой пример из интернета, выкидываем из yii2 activerecord, и поехали (но, чесслово, не понимаю, зачем тогда нужен такой монолит как yii2).
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
Да весь этот раздел на форуме. Вы уже все соседние темы прочитали?magicoder писал(а):Знаю, что подобные темы уже были.
Архитектура - тема об абстракциях, а не о реализации. Идеи и принципы в ней одни и те же независимо от языка программирования. Потому и разрозненная и на форуме не очень распространённая, что это отдельный пласт информации, одним фреймворком и языком не ограничивающаяся.magicoder писал(а):Однако, решил открыть данную тему, чтобы люди, который "знают толк" в построении правильной архитектуры приложения (сайта) на yii2 могли поделиться примерами кода.
Язык PHP сам по себе никогда не подстёгивал разработчиков к построение архитектуры, так как даже нормального ООП в нём до последних лет практически не было. В отличие, например, от Java, где паттернам и энтерпрайзу учат "с пелёнок". Поэтому изучать всё это на примере PHP нет смысла. А на Yii2...
Yii2 - это Yii1, переписанный на пространства имён. Сильных архитектурных изменений в нём при переписывании не произошло. Соответственно, имеем в нём сейчас то, что было "модным" ещё в "лихих нулевых" со времён первой версии: свои подходы к геттерам и сеттерам, публичные поля, синглтоны, статические методы, сильную связанность из-за вездесущего наследования и экономии на классах, несовместимость с новыми PSR - то есть своеобразный "коммунизм" с самозамкнутостью и железным зановесом. Поэтому-то с такой весьма странной внутренней архитектурой он и выглядит белой вороной на фоне остальных.
К чему приводят внутренние архитектурные странности? Хорошим стилем можно и на Wordpress приложения программировать, если есть соответствующие навыки как при этом победить изнутри сам Wordpress. Но в какой-то момент времени число мешающих факторов со стороны этой CMS зашкалит критический уровень, терпение закончится и разработчик примет решение перейти на более удобную внутри CMS или фреймворк. Такая же ситуация и с "лёкими" фреймворками и дешёвыми автомобилями. Сначала получаем удовольствие от внешнего вида и всем советуем. А потом по необходимости залазием под капот во внутренности, а там... А через год вечного ковыряния, залатывания дыр и доводки напильником в гараже хочется выбросить это всё и купить что-то покруче.
И из-за лёгкости изучения Yii2 у многих самый первый в их жизни. Symfony и прочие вещи для новичков кажутся слишком сложными, да и лень документацию на английском читать. А простой Yii2 для них в самый раз. Да и разработчиков на нём не сильно много, так как фреймворк более как продукт любительский, сделанный в свободное время несколькими разработчиками. Целенаправленного маркетинга и сопутствующей инфраструктуры у него нет. Поэтому если учесть, что в Yii2, наверное, 70-90% новичков, которые только-только начинают изучать ООП после процедурных CMS, то обилия статей и прочей информации о лучших практиках среди его пользователей найти весьма сложно. Только статью от 2Gis на Хабре и, возможно, ещё пару блогов. А так даже более-менее сносное ООП в проектах на Yii2 почти не встречается.magicoder писал(а):...построении правильной архитектуры приложения (сайта) на yii2
Соответственно, ищите информацию об архитектуре по тем языкам и фреймворкам, где много народа и где эта архитектура давно уже есть. Да и форум - это больше просто для подсказок новичкам от новичков.
В сервисах, репозиториях и все этих вещах ничего особенного и сверхъестественного нет. Это всё естественным образом вытекает из исходных принципов того самого ООП, которое придумали уже черт знает когда и которое всем лень учить. Это целая парадигма, а не только синтаксис. Если перекинуть все свои процедуры и функции в классы, то объектно-ориентированным наш код сам по себе не станет.magicoder писал(а):Поэтому, если Вы сильны в архитектуре и можете поделиться с сообществом кодом, как лучше организовать модели и контроллеры, как оформить классы сервисов и репозиториев, уменьшив тем самым зависимость от фреймворка - прошу поделиться опытом в данной теме.
Конкретно в этом примере по обобщающему паттерну наш "контроллер" должен только принимать информацию из одного места и перекидывать в другое. На то он и контроллер, что должен только контролировать процесс, не делая ничего самостоятельно. Принял GET или POST-параметры и закинул в модель или в рендерер. "Модель" должна моделировать сущности и процессы предметной области (домена). Сущности с их поведением описываются в "сущностях", а вспомогательные операции - во вспомогательных объектах - "сервисах домена". Иногда контроллер у нас не одно действие выполняет, а порой по несколько объектов заполняет и их друг с другом связывает. Ну или другие вещи. А из контроллера нужно этот код куда-то вынести, чтобы контроллеры оставить пустыми. Это и будут у нас "сервисы приложения".
Если у Вас в коде есть разделение на ядро и обвязку, то при миграции на другую БД или фреймворк нужно будет только поменять обвязку. А если нет - то придётся переписывать весь код. Соответственно, делаем независимое от фреймворка ядро на чистом PHP, а весь фреймворковский код помещаем в обвязку. На этом многослойная архитектура и построена. Слой UI представляет собой контроллеры, шаблонизатор и формы ввода. Кода с логикой там нет. Только представления, формочки и клиентская валидация. Контроллер вызывает методы операционного слоя (уровня приложения). Слоем доменной модели является само вышеупомянутое ядро с интерфейсами адаптеров обвязки. В нём весь код. Слоем инфраструктуры являются классы реализации этой обвязки. То есть переходники (адаптеры) для доступа к базе данных, мэйлеру, хешерам паролей и прочим фреймворковским штукам.
Весь секрет - инкапсуляция изменчивости: делаем независимое ядро, взаимодействующее со внешним миром через адаптеры. Нужно что-то поменять - просто переписываем адаптер.
За полгода углубленнного изучения независимых архитектур осознал, что программировать независимый код несложно. Просто многим лениво. Если хочется именно на примерах, то на чистое ООП и независимость от фреймворков идёт весь упор в девятнадцати примерах интенсива. Там пять дней с этими примерами по четыре часа объяснения и практики и ещё пятичасовой мастер-класс по приложению с сервисным слоем на Yii2. Можно вписаться на следующий поток или уломать автора продать записи прошедшего.
За несколько лет всё подробно описано в статьях, слайдах, книгах и видео. Кое-что есть и на русском языке. Это естественный отбор. Кто осилил это всё собрать и освоить, тот становится архитектором. Кто не осилил - не становится.magicoder писал(а):Это очень важно, чтобы такие примеры были в одной теме, потому-что вся информация разрознена и приходится собирать ее по кусочкам по всему интернету и на форуме.
Последний раз редактировалось ElisDN 2016.07.24, 19:24, всего редактировалось 4 раза.
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
Ну и примеры:
Код контроллера на Yii2:
Код контроллера на Symfony3:
Код контроллера на Laravel5:
Код обработчика (операционный слой / слой приложения):
Код контроллера на Yii2:
Код: Выделить всё
public function actionCreate()
{
$form = new ProductCreateForm();
if ($form->load(Yii::$app->request->post()) && $form->validate()) {
$this->commandBus->execute(new ProductCreateCommand(
$form->title,
$form->price,
$form->category,
$form->content
));
return $this->redirect(['index']);
}
return $this->render('create', [
'createForm' => $form,
]);
}
Код: Выделить всё
public function createAction(Request $request)
{
$form = $this->createForm(ProductCreateType::class);
$form->handleRequest($request);
if ($form->isValid()) {
$data = $form->getData();
$this->commandBus->execute(new ProductCreateCommand(
$data->getTitle(),
$data->getPrice(),
$data->getCategory()->getId(),
$data->getСontent()
));
return $this->redirectToRoute('products');
}
return $this->render('products/create.html.twig', [
'createForm' => $form->createView(),
]);
}
Код: Выделить всё
public function store(ProductCreateRequest $request)
{
$this->commandBus->execute(new ProductCreateCommand(
$request->get('title'),
$request->get('price'),
$request->get('category'),
$request->get('content')
));
return redirect()->route('products');
}
Код: Выделить всё
class ProductCreateHandler
{
private $categoryRepository;
private $productRepository;
private $eventDispatcher;
public function __construct(
CategoryRepositoryInterface $categoryRepository,
ProductRepositoryInterface $productRepository,
EventDispatcherInterface $eventDispatcher
)
{
$this->categoryRepository = $categoryRepository;
$this->productRepository = $productRepository;
$this->eventDispatcher = $eventDispatcher;
}
public function handle(ProductCreateCommand $command)
{
$category = $this->categoryRepository->find($command->category);
$id = $this->productRepository->getNextId();
$product = Product::create($id, $commant->title, $command->price, $command->content);
$product->assignCategory($category);
$this->productRepository->add($product);
$this->eventDispatcher->dispatch($product->releaseEvents());
}
}
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
Столько информации, не сомненно полезной, но нужен пример.Понятный, доступный пример из практики на yii2. Хотя бы какой-то связанный между собой по смыслу код. Потому-что текста и так много. Код, что выше наверное нужен и полезен, но хотелось бы что-то более связное. Например, контроллер (с одним методом для демонстрации), модель , класс сервиса и репозитория. И все это связано между собой.
Разработка на yii2 или чистом php.| email: [email protected] | skype: for-web1
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
И да, я был на Вашем интенсиве ) Маркетинг, тоже большое искусство.
Последний раз редактировалось magicoder 2016.07.24, 22:05, всего редактировалось 1 раз.
Разработка на yii2 или чистом php.| email: [email protected] | skype: for-web1
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
https://github.com/codeliner/php-ddd-ca ... /Cargo.phpmagicoder писал(а):Например, контроллер (с одним методом для демонстрации), модель , класс сервиса и репозитория. И все это связано между собой.
https://github.com/codeliner/php-ddd-ca ... ervice.php
https://github.com/codeliner/php-ddd-ca ... sitory.php
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
Понял. Всем лень. (
Пожалуйста, если есть возможность и желание - наберите вкратце код для yii2. Чтобы все всем стало ясно раз и на всегда. Пусть это будет на примере вывода какой-нибудь статьи блога. Чтобы все было понятно, кратко. Относительно yii2.
Пожалуйста, если есть возможность и желание - наберите вкратце код для yii2. Чтобы все всем стало ясно раз и на всегда. Пусть это будет на примере вывода какой-нибудь статьи блога. Чтобы все было понятно, кратко. Относительно yii2.
Разработка на yii2 или чистом php.| email: [email protected] | skype: for-web1
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
не играйте в обидки. Не поняли - попросите объяснить еще раз.magicoder писал(а):Понял. Всем лень. (
слоистая архитектура подразумевает под собой слабую зависимость от фреймворка
берем любой пример из интернета, выкидываем из yii2 activerecord, и поехали
Архитектура - тема об абстракциях, а не о реализации
"контроллер" должен только принимать информацию из одного места и перекидывать в другое
инкапсуляция изменчивости: делаем независимое ядро, взаимодействующее со внешним миром через адаптеры. Нужно что-то поменять - просто переписываем адаптер.
еще раз - слоистая архитектура подразумевает НЕЗАВИСИМОСТЬ от реализаций, поэтому 80% кода не зависит от фреймворка и реализовывается одинаково без участия фреймворков.Код контроллера на Yii2:
Код: Выделить всё
public function actionCreate() { $form = new ProductCreateForm(); if ($form->load(Yii::$app->request->post()) && $form->validate()) { $this->commandBus->execute(new ProductCreateCommand( $form->title, $form->price, $form->category, $form->content )); return $this->redirect(['index']); } return $this->render('create', [ 'createForm' => $form, ]); }
Все, что вы можете взять из yii2 - это контроллеры/вьюшки (+валидация форм в них) и db-слой (соединение - не модели). Первое ничем не отличается от стандартного использования. Второе - обычные запросы в БД через коннекшн (см. соседнюю тему - там неплохо создано приложение на базе yii2). Все остальное к yii2 не относится.
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
Дмитрий показал пример экшна на yii2 - это все, что нужно. Остальное реализуется независимо.magicoder писал(а):Пожалуйста, если есть возможность и желание - наберите вкратце код для yii2. Чтобы все всем стало ясно раз и на всегда. Пусть это будет на примере вывода какой-нибудь статьи блога. Чтобы все было понятно, кратко. Относительно yii2.
Если не хотите начать, прося разжевать вам, то вероятно рановато.
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
magicoder писал(а):Понятный, доступный пример из практики на yii2. Хотя бы какой-то связанный между собой по смыслу код. Потому-что текста и так много. Код, что выше наверное нужен и полезен, но хотелось бы что-то более связное. Например, контроллер (с одним методом для демонстрации), модель , класс сервиса и репозитория. И все это связано между собой.
Тогда весьма странный вопрос, учитывая, что в соседних темах есть примеры многих вещей и что с интенсива у Вас уже есть сущность Student и репозитории TXTStudentRepository и XMLStudentRepository со второго урока. А также полный рабочий пример сайта на Yii2 с последнего урока: контроллеры InterviewController и EmployeeController с формами, их сущности Interview и Employee, полностью фреймворконезависимый сервис приложения StaffService, инфраструктурные сервисы Notifier, TransactionManager, базовые репозитории EmployeeRepository и остальное.magicoder писал(а):И да, я был на Вашем интенсиве ) Маркетинг, тоже большое искусство.
Всё, что там осталось для универсальности - убрать ActiveRecord, оставив от моделей простые классы с приватными полями, и прописать поиск через Query и сохранение через Yii::$app->db->createCommand(). в репозиториях. Ну и запросы Employee::findOne($id) в контроллере и Employee::find() в EmployeeSearch поменять на $this->employeeService->find($id) и $this->employeeService->findAllBySearch($condition, $limit, $offset).
А если всего вышеперечисленного в интенсиве не заметили и там примеров не нашли, то, вероятно, дело не в лыжах и не в маркетинге.
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
Код. Нужен код примера. Хоть на примере вывода статьи блога. Если Вы действительно знаете - напишите код. Все.
Разработка на yii2 или чистом php.| email: [email protected] | skype: for-web1
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
Давайте не будем про "интенив". Если Вы можете - наберите код, коротенький, для примера. Чтобы наглядно было видно, как реализовать взаимодействие между сервисом, репозиторием, контроллером и моделью в рамках фреймворка yii2. Это будет лучшим примером того, как Вы владеете вопросом.ElisDN писал(а):magicoder писал(а): А если всего вышеперечисленного в интенсиве не заметили и там примеров не нашли, то, вероятно, дело не в лыжах и не в маркетинге.
Разработка на yii2 или чистом php.| email: [email protected] | skype: for-web1
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
Уже набрали длинненький для примера:magicoder писал(а):Если Вы можете - наберите код, коротенький, для примера. Чтобы наглядно было видно, как реализовать взаимодействие между сервисом, репозиторием, контроллером и моделью в рамках фреймворка yii2. Это будет лучшим примером того, как Вы владеете вопросом.
Контроллер и хэндлер для CommandBus: viewtopic.php?f=34&t=37556#p193118
Форма, контроллер и UserService вместо CommandBus: viewtopic.php?f=34&t=36725&start=20#p188218
Код CommandBus и валидация команд: viewtopic.php?f=34&t=36725&start=60#p188542
Хендлер, взаимодействующий с сервисами: viewtopic.php?f=34&t=36725&start=100#p190366
Разбиение сущности на ValueObjects: viewtopic.php?f=34&t=36725&start=140#p192540
Код сущности User, хэндлеров и контроллеров: viewtopic.php?f=34&t=36725&start=160#p192900
Альтернативный код сущности User: viewtopic.php?f=34&t=36725&start=180#p192952
И репозиторий:
Код: Выделить всё
class UserRepository implements UserRepositoryInterface
{
public function find($id)
{
if (!$data = (new Query())->select('*')->from('{{%user}}')->andWhere(['id' => $id])->one()) {
throw new NotFoundException('User not found.');
}
return new User($data['id'], $data['email'], $data['password_hash'], $data['status']);
}
public function add(User $user)
{
$result = Yii::$app->db->createCommand()->insert('{{$user}}', [
'id' => $user->getId(),
'email' => $user->getEmail(),
'password_hash' => $user->getPassword(),
'status' => $user->getStatus(),
])->execute();
}
public function save(User $user)
{
$result = Yii::$app->db->createCommand()->update('{{$user}}', [
'email' => $user->getEmail(),
'password_hash' => $user->getPassword(),
'status' => $user->getStatus(),
], [
'id' => $user->getId(),
])->execute();
}
public function remove(User $user)
{
$result = Yii::$app->db->createCommand()->delete('{{$user}}', [
'id' => $user->getId(),
])->execute();
}
}
Последний раз редактировалось ElisDN 2016.07.28, 12:53, всего редактировалось 2 раза.
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
Длинненький ).magicoder писал(а):Уже набрали длинненький для примера:
Зачем эта большая сборная? Неужели нельзя показать простой код в качестве примера тут. Пусть там будет одно свойство (например $title), которое можно заполнять (обновлять). Ну чтобы все было тут, в теме. Чтобы видно было как эти классы связаны, какие методы задействованы. Как еще объяснить. Не обижайтесь, но это будет полезно и наглядно для многих и многие Вам спасибо скажут.magicoder писал(а):Знаю, что подобные темы уже были. Однако, решил открыть данную тему, чтобы люди, который "знают толк" в построении правильной архитектуры приложения (сайта) на yii2 могли поделиться примерами кода. Это очень важно, чтобы такие примеры были в одной теме, потому-что вся информация разрознена и приходится собирать ее по кусочкам по всему интернету и на форуме.
Поэтому, если Вы сильны в архитектуре и можете поделиться с сообществом кодом, как лучше организовать модели и контроллеры, как оформить классы сервисов и репозиторием, уменьшив тем самым зависимость от фреймворка - прошу поделиться опытом в данной теме.
Разработка на yii2 или чистом php.| email: [email protected] | skype: for-web1
- slavcodev
- Сообщения: 3134
- Зарегистрирован: 2009.04.02, 21:42
- Откуда: Valencia
- Контактная информация:
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
magicoder, модель с одним свойством title, лучше делать с ActiveRecord и обычным CRUD. Все: работодатель, ревьювер, кодер который будет это поддерживать после тебя, все скажут только спасибо!
Жду Yii 3!
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
Я имею ввиду для примера, чтобы не городить кучу кода. Чтобы было наглядно и понятно. Ничего лишнего. Вроде бы простая понятная просьба ...slavcodev писал(а):magicoder, модель с одним свойством title, лучше делать с ActiveRecord и обычным CRUD. Все: работодатель, ревьювер, кодер который будет это поддерживать после тебя, все скажут только спасибо!
Разработка на yii2 или чистом php.| email: [email protected] | skype: for-web1
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
Форма, форма, экшен, экшен, сервис, шина, команда, хэндлер, репозиторий, конфиг контейнера. Вот и сборная.magicoder писал(а):Зачем эта большая сборная?
Можно. Копируем оттуда и вставляем сюда.magicoder писал(а):Неужели нельзя показать простой код в качестве примера тут.
С одним полем будет всего два метода. С ним не будет вспомогательных сервисов и VO.magicoder писал(а):Пусть там будет одно свойство (например $title), которое можно заполнять (обновлять). Ну чтобы все было тут, в теме. Чтобы видно было как эти классы связаны, какие методы задействованы.
В этом разделе только zelenin, ElisDN и slavcodev друг с другом переписываются. Остальным это нафиг не надо.magicoder писал(а):Это будет полезно и наглядно для многих и многие Вам спасибо скажут.
Последний раз редактировалось ElisDN 2016.07.25, 16:03, всего редактировалось 1 раз.
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
Пусть будет два метода. Покажите инфраструктуру. Пусть в реальном приложении с двумя методами нет смысла городить слоистую архитектуру. Но тут-то для примера можно .ElisDN писал(а): С одним полем будет всего два метода. С ним не будет вспомогательных сервисов и VO.
Разработка на yii2 или чистом php.| email: [email protected] | skype: for-web1
Re: Сервисы и репозитории. Слоистая архитектура. Примеры.
так вы объясните, чем вам примеры по ссылкам не угодили? вам кажется, что это не то или это ваша принципиальная позиция, что тот код надо скопипастить сюда?magicoder писал(а):Пусть будет два метода. Покажите инфраструктуру. Пусть в реальном приложении с двумя методами нет смысла городить слоистую архитектуру. Но тут-то для примера можно .ElisDN писал(а): С одним полем будет всего два метода. С ним не будет вспомогательных сервисов и VO.