From 4eb46523b95f02f33a0238f4a1bfeed2d99d6e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=93=D1=80=D0=B8=D0=B3=D0=BE=D1=80=D0=B8=D0=B9=20=D0=9A?= =?UTF-8?q?=D0=B0=D1=80=D0=BC=D0=B0=D0=BD?= Date: Sun, 18 Feb 2024 14:12:02 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 162 +++++++++++++++--------------------------------------- 1 file changed, 45 insertions(+), 117 deletions(-) diff --git a/README.md b/README.md index 724bf47b9..c2e046f7a 100644 --- a/README.md +++ b/README.md @@ -1,133 +1,61 @@ -Введение) +Текст домашнего задания -1. У меня на работе проект написан на Laravel -2. Мы используем библиотеку graphql для api - -- Для того чтобы мне было понятно, как работать с DDD я поднял чистый laravel, поставил туда Rebing\GraphQL -- Для понимания принципов DDD не отвлекаясь на сложную логику специально упростил задачу. -- Задача: сохранить данные в БД, которые пришли. +Разрабатываем часть интернет-ресторана. Продаёт он фаст-фуд. +1. Фабричный метод будет отвечать за генерацию базового продукта-прототипа: бургер, сэндвич или хот-дог +2. При готовке каждого типа продукта Фабричный метод будет добавлять составляющие к базовому продукту либо по рецепту, либо по пожеланию клиента (салат, лук, перец и т.д.) +3. Цепочка обязанностей подписывается на статус приготовления и отправляет оповещения о том, что изменился статус приготовления продукта. +4. Стратегия будет отвечать за готовку продукта +5. Абстрактная фабрика будет генерировать заказы с сайта, из магазина и через телефон. +6. Все сущности должны по максимуму генерироваться через DI. +
-Вот что получилось -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 то мы должны описать - - что к нам придет и какого это типа - - что мы отдаем и какого это типа - - правила валидации для данных +
+## Описание по пунктам ДЗ -За логику отвечает класс 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