-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
45 additions
and
117 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,133 +1,61 @@ | ||
Введение) | ||
Текст домашнего задания | ||
|
||
1. У меня на работе проект написан на Laravel | ||
2. Мы используем библиотеку graphql для api | ||
|
||
- Для того чтобы мне было понятно, как работать с DDD я поднял чистый laravel, поставил туда Rebing\GraphQL | ||
- Для понимания принципов DDD не отвлекаясь на сложную логику специально упростил задачу. | ||
- Задача: сохранить данные в БД, которые пришли. | ||
Разрабатываем часть интернет-ресторана. Продаёт он фаст-фуд. | ||
1. Фабричный метод будет отвечать за генерацию базового продукта-прототипа: бургер, сэндвич или хот-дог | ||
2. При готовке каждого типа продукта Фабричный метод будет добавлять составляющие к базовому продукту либо по рецепту, либо по пожеланию клиента (салат, лук, перец и т.д.) | ||
3. Цепочка обязанностей подписывается на статус приготовления и отправляет оповещения о том, что изменился статус приготовления продукта. | ||
4. Стратегия будет отвечать за готовку продукта | ||
5. Абстрактная фабрика будет генерировать заказы с сайта, из магазина и через телефон. | ||
6. Все сущности должны по максимуму генерироваться через DI. | ||
|
||
<hr> | ||
|
||
Вот что получилось | ||
1. Вызов старого и нового кода идет через файл app/config/graphql.php | ||
|
||
``` | ||
'mutation' => [ | ||
'create_order' => CreateOrderMutation::class, | ||
'create_order_old' => OldCreateOrderMutation::class, | ||
], | ||
``` | ||
1. У меня на работе проект написан на Laravel | ||
2. Мы используем библиотеку graphql для api | ||
|
||
2. Как работает старый код. | ||
- Для того чтобы мне было понятно, как работать с DDD я поднял чистый laravel, поставил туда Rebing\GraphQL | ||
|
||
Входная точка App\OldCode\GraphQL\Mutations\OldCreateOrderMutation по сути является контроллером, | ||
но, так как это graphql то мы должны описать | ||
- что к нам придет и какого это типа | ||
- что мы отдаем и какого это типа | ||
- правила валидации для данных | ||
<hr> | ||
|
||
## Описание по пунктам ДЗ | ||
|
||
За логику отвечает класс CreateOrderService, так же в нем хранятся правила валидации в статическом методе на случай, | ||
если они понадобятся еще где-то | ||
1. класс App\Domains\Order\Domain\Factories\Product\ProductFactory | ||
2. класс App\Domains\Order\Domain\Factories\Product\ProductFactory метод addIngredientsToProduct() | ||
3. классы | ||
- создание цепочки - App\Domains\Order\Domain\Subscribers\SendNotificationsService | ||
- изменения статуса тут App\Domains\Order\Application\CockProductProcessUseCase | ||
- запуск цепочки тут App\Domains\Order\Application\CockProductProcessUseCase ($this->publisher->notify($product);) | ||
- подписание в сервис провайдере App\Infrastructure\Providers\AppServiceProvider | ||
|
||
``` | ||
class OldCreateOrderMutation extends Mutation | ||
{ | ||
protected $attributes = [ | ||
'name' => 'create_order_old', | ||
'description' => 'Создание заявки старый код', | ||
]; | ||
public function type(): Type | ||
private function registerPublishers(): void | ||
{ | ||
return Type::int(); | ||
$this->app->bind(PublisherProductChangeStatusInterface::class, function ($app) { | ||
$publisher = new PublisherProductChangeStatus(); | ||
$publisher->subscribe(new SendNotificationsService()); | ||
}); | ||
} | ||
public function args(): array | ||
{ | ||
return [ | ||
'email' => [ | ||
'type' => Type::string(), | ||
'description' => "Обязательный. email", | ||
], | ||
'title' => [ | ||
'type' => Type::string(), | ||
'description' => "Обязательный. Заголовок заявки", | ||
], | ||
'description' => [ | ||
'type' => Type::string(), | ||
'description' => "Обязательный. Описание заявки", | ||
], | ||
]; | ||
} | ||
protected function rules(array $args = []): array | ||
{ | ||
return CreateOrderService::rules($args); | ||
} | ||
public function resolve($root, $args, $context, ResolveInfo $info) | ||
{ | ||
$service = new CreateOrderService(); | ||
return $service->run($args); | ||
} | ||
} | ||
``` | ||
|
||
|
||
|
||
|
||
``` | ||
use App\OldCode\Models\Order; | ||
use Illuminate\Support\Arr; | ||
class CreateOrderService | ||
4. классы | ||
- стратения 1 App\Domains\Order\Domain\Strategies\Cock\FryingPanCockStrategy | ||
- стратения 2 App\Domains\Order\Domain\Strategies\Cock\GrillCockStrategy | ||
- выбор стратегии повесил в сервис провайдер App\Infrastructure\Providers\AppServiceProvider | ||
|
||
``` | ||
private function registerStrategies(): void | ||
{ | ||
public function run (array $args) : int | ||
{ | ||
$order = new Order(); | ||
$order->email = Arr::get($args, 'email'); | ||
$order->title = Arr::get($args, 'title'); | ||
$order->description = Arr::get($args, 'description'); | ||
$order->save(); | ||
return $order->id; | ||
} | ||
public static function rules(array $args = []) | ||
{ | ||
return [ | ||
'email' => ['required', 'string', 'email'], | ||
'title' => ['required', 'string', 'max:50'], | ||
'description' => ['required', 'string', 'max:255'], | ||
]; | ||
} | ||
$this->app->singleton(CockStrategyInterface::class, GrillCockStrategy::class); | ||
} | ||
``` | ||
|
||
4. Новый код DDD | ||
|
||
Входная точка App\Domains\Order\Infrastructure\GraphQL\Mutations\CreateOrderService | ||
|
||
1) что я сделал это код фреймворка в папке app перенес в app/Infrastructure | ||
2) создал папку app/Domains в нее будут добавляться модули | ||
3) создал папку app/Domains/Order - модуль для работы с Order | ||
4) в папке app/Domains/Order разложил код на 3 уровня | ||
|
||
Далее я сделал DTO для передачи данных из мутации в CreateOrderUseCase, | ||
Создал CreateOrderUseCase, добавил ValueObjects для описания полей сущности, написал интерфейс для взаимодействия | ||
с БД, а реализацию положин на слой инфрастуктуры. Все сделал как на уроке. | ||
|
||
|
||
5. Что я понял работая с DDD | ||
- Валидация на graphQl работает довольно хорошо. + хорошая обработка ошибок. | ||
- Отвалидированные данные, оборачиваюсят в DTO и отдаются на слой приложения. Тут мы полностью ушли от привязки к graphql. | ||
Это хорошо. | ||
- Возникает не то, что избыточная валидация, ее много не бывает, но довольно тяжело это все писать. Одно и тоже на разных слоях. | ||
Думаю это дань стабильности, но скорость разработки падает довольно сильно. | ||
- Из-за того что в коде используется только 1 сущность, вроде все хорошо, но пока не знаю, что будет если | ||
у order будет много связных данных, например user, company, depots, truck итд. При создании такой сущности приходит около | ||
30 параметров, их нужно будет записывать в DTO потом каждое значение в VO. Нужно смотреть. В уроке не раскрыто это. | ||
``` | ||
|
||
5. Создал 3 разных запроса api имитирующий создание заказа с разных мест. | ||
- app/Domains/Order/Infrastructure/GraphQL/Mutations/CreateOrder/CreateOrderFromPhoneMutation.php | ||
- app/Domains/Order/Infrastructure/GraphQL/Mutations/CreateOrder/CreateOrderFromShopMutation.php | ||
- app/Domains/Order/Infrastructure/GraphQL/Mutations/CreateOrder/CreateOrderFromSiteMutation.php | ||
|
||
- Самое важное, что старый код невозможно нормально тестировать | ||
в App\Domains\Order\Application\CreateOrderUseCase метод run они передают нужную абстрактную фабрику | ||
- App\Domains\Order\Domain\Factories\Order\OrderPhoneFactory | ||
- App\Domains\Order\Domain\Factories\Order\OrderShopFactory | ||
- App\Domains\Order\Domain\Factories\Order\OrderSiteFactory |